#                                                          -*- shell-script -*-
#
#   bash_completion - programmable completion functions for bash 4.2+
#
#   Copyright © 2006-2008, Ian Macdonald <ian@caliban.org>
#             © 2009-2020, Bash Completion Maintainers
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2, or (at your option)
#   any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software Foundation,
#   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
#   The latest version of this software can be obtained here:
#
#   https://github.com/scop/bash-completion

BASH_COMPLETION_VERSINFO=(2 11)

if [[ $- == *v* ]]; then
    BASH_COMPLETION_ORIGINAL_V_VALUE="-v"
else
    BASH_COMPLETION_ORIGINAL_V_VALUE="+v"
fi

if [[ ${BASH_COMPLETION_DEBUG-} ]]; then
    set -v
else
    set +v
fi

# Blacklisted completions, causing problems with our code.
#
_blacklist_glob='@(acroread.sh)'

# Turn on extended globbing and programmable completion
shopt -s extglob progcomp

# A lot of the following one-liners were taken directly from the
# completion examples provided with the bash 2.04 source distribution

# start of section containing compspecs that can be handled within bash

# user commands see only users
complete -u groups slay w sux

# bg completes with stopped jobs
complete -A stopped -P '"%' -S '"' bg

# other job commands
complete -j -P '"%' -S '"' fg jobs disown

# readonly and unset complete with shell variables
complete -v readonly unset

# set completes with set options
complete -A setopt set

# shopt completes with shopt options
complete -A shopt shopt

# helptopics
complete -A helptopic help

# unalias completes with aliases
complete -a unalias

# type and which complete on commands
complete -c command type which

# builtin completes on builtins
complete -b builtin

# start of section containing completion functions called by other functions

# Check if we're running on the given userland
# @param $1 userland to check for
_userland()
{
    local userland=$(uname -s)
    [[ $userland == @(Linux|GNU/*) ]] && userland=GNU
    [[ $userland == "$1" ]]
}

# This function sets correct SysV init directories
#
_sysvdirs()
{
    sysvdirs=()
    [[ -d /etc/rc.d/init.d ]] && sysvdirs+=(/etc/rc.d/init.d)
    [[ -d /etc/init.d ]] && sysvdirs+=(/etc/init.d)
    # Slackware uses /etc/rc.d
    [[ -f /etc/slackware-version ]] && sysvdirs=(/etc/rc.d)
    return 0
}

# This function checks whether we have a given program on the system.
#
_have()
{
    # Completions for system administrator commands are installed as well in
    # case completion is attempted via `sudo command ...'.
    PATH=$PATH:/usr/sbin:/sbin:/usr/local/sbin type $1 &>/dev/null
}

# Backwards compatibility for compat completions that use have().
# @deprecated should no longer be used; generally not needed with dynamically
#             loaded completions, and _have is suitable for runtime use.
have()
{
    unset -v have
    _have $1 && have=yes
}

# This function checks whether a given readline variable
# is `on'.
#
_rl_enabled()
{
    [[ "$(bind -v)" == *$1+([[:space:]])on* ]]
}

# This function shell-quotes the argument
quote()
{
    local quoted=${1//\'/\'\\\'\'}
    printf "'%s'" "$quoted"
}

# @see _quote_readline_by_ref()
quote_readline()
{
    local ret
    _quote_readline_by_ref "$1" ret
    printf %s "$ret"
} # quote_readline()

# This function shell-dequotes the argument
dequote()
{
    eval printf %s "$1" 2>/dev/null
}

# Assign variable one scope above the caller
# Usage: local "$1" && _upvar $1 "value(s)"
# Param: $1  Variable name to assign value to
# Param: $*  Value(s) to assign.  If multiple values, an array is
#            assigned, otherwise a single value is assigned.
# NOTE: For assigning multiple variables, use '_upvars'.  Do NOT
#       use multiple '_upvar' calls, since one '_upvar' call might
#       reassign a variable to be used by another '_upvar' call.
# See: https://fvue.nl/wiki/Bash:_Passing_variables_by_reference
_upvar()
{
    echo "bash_completion: $FUNCNAME: deprecated function," \
        "use _upvars instead" >&2
    if unset -v "$1"; then # Unset & validate varname
        if (($# == 2)); then
            eval $1=\"\$2\" # Return single value
        else
            eval $1=\(\"\$"{@:2}"\"\) # Return array
        fi
    fi
}

# Assign variables one scope above the caller
# Usage: local varname [varname ...] &&
#        _upvars [-v varname value] | [-aN varname [value ...]] ...
# Available OPTIONS:
#     -aN  Assign next N values to varname as array
#     -v   Assign single value to varname
# Return: 1 if error occurs
# See: https://fvue.nl/wiki/Bash:_Passing_variables_by_reference
_upvars()
{
    if ! (($#)); then
        echo "bash_completion: $FUNCNAME: usage: $FUNCNAME" \
            "[-v varname value] | [-aN varname [value ...]] ..." >&2
        return 2
    fi
    while (($#)); do
        case $1 in
            -a*)
                # Error checking
                [[ ${1#-a} ]] || {
                    echo "bash_completion: $FUNCNAME:" \
                        "\`$1': missing number specifier" >&2
                    return 1
                }
                printf %d "${1#-a}" &>/dev/null || {
                    echo bash_completion: \
                        "$FUNCNAME: \`$1': invalid number specifier" >&2
                    return 1
                }
                # Assign array of -aN elements
                [[ "$2" ]] && unset -v "$2" && eval $2=\(\"\$"{@:3:${1#-a}}"\"\) &&
                    shift $((${1#-a} + 2)) || {
                    echo bash_completion: \
                        "$FUNCNAME: \`$1${2+ }$2': missing argument(s)" \
                        >&2
                    return 1
                }
                ;;
            -v)
                # Assign single value
                [[ "$2" ]] && unset -v "$2" && eval $2=\"\$3\" &&
                    shift 3 || {
                    echo "bash_completion: $FUNCNAME: $1:" \
                        "missing argument(s)" >&2
                    return 1
                }
                ;;
            *)
                echo "bash_completion: $FUNCNAME: $1: invalid option" >&2
                return 1
                ;;
        esac
    done
}

# Reassemble command line words, excluding specified characters from the
# list of word completion separators (COMP_WORDBREAKS).
# @param $1 chars  Characters out of $COMP_WORDBREAKS which should
#     NOT be considered word breaks. This is useful for things like scp where
#     we want to return host:path and not only path, so we would pass the
#     colon (:) as $1 here.
# @param $2 words  Name of variable to return words to
# @param $3 cword  Name of variable to return cword to
#
__reassemble_comp_words_by_ref()
{
    local exclude i j line ref
    # Exclude word separator characters?
    if [[ $1 ]]; then
        # Yes, exclude word separator characters;
        # Exclude only those characters, which were really included
        exclude="[${1//[^$COMP_WORDBREAKS]/}]"
    fi

    # Default to cword unchanged
    printf -v "$3" %s "$COMP_CWORD"
    # Are characters excluded which were former included?
    if [[ -v exclude ]]; then
        # Yes, list of word completion separators has shrunk;
        line=$COMP_LINE
        # Re-assemble words to complete
        for ((i = 0, j = 0; i < ${#COMP_WORDS[@]}; i++, j++)); do
            # Is current word not word 0 (the command itself) and is word not
            # empty and is word made up of just word separator characters to
            # be excluded and is current word not preceded by whitespace in
            # original line?
            while [[ $i -gt 0 && ${COMP_WORDS[i]} == +($exclude) ]]; do
                # Is word separator not preceded by whitespace in original line
                # and are we not going to append to word 0 (the command
                # itself), then append to current word.
                [[ $line != [[:blank:]]* ]] && ((j >= 2)) && ((j--))
                # Append word separator to current or new word
                ref="$2[$j]"
                printf -v "$ref" %s "${!ref-}${COMP_WORDS[i]}"
                # Indicate new cword
                ((i == COMP_CWORD)) && printf -v "$3" %s "$j"
                # Remove optional whitespace + word separator from line copy
                line=${line#*"${COMP_WORDS[i]}"}
                # Start new word if word separator in original line is
                # followed by whitespace.
                [[ $line == [[:blank:]]* ]] && ((j++))
                # Indicate next word if available, else end *both* while and
                # for loop
                ((i < ${#COMP_WORDS[@]} - 1)) && ((i++)) || break 2
            done
            # Append word to current word
            ref="$2[$j]"
            printf -v "$ref" %s "${!ref-}${COMP_WORDS[i]}"
            # Remove optional whitespace + word from line copy
            line=${line#*"${COMP_WORDS[i]}"}
            # Indicate new cword
            ((i == COMP_CWORD)) && printf -v "$3" %s "$j"
        done
        ((i == COMP_CWORD)) && printf -v "$3" %s "$j"
    else
        # No, list of word completions separators hasn't changed;
        for i in "${!COMP_WORDS[@]}"; do
            printf -v "$2[i]" %s "${COMP_WORDS[i]}"
        done
    fi
} # __reassemble_comp_words_by_ref()

# @param $1 exclude  Characters out of $COMP_WORDBREAKS which should NOT be
#     considered word breaks. This is useful for things like scp where
#     we want to return host:path and not only path, so we would pass the
#     colon (:) as $1 in this case.
# @param $2 words  Name of variable to return words to
# @param $3 cword  Name of variable to return cword to
# @param $4 cur  Name of variable to return current word to complete to
# @see __reassemble_comp_words_by_ref()
__get_cword_at_cursor_by_ref()
{
    local cword words=()
    __reassemble_comp_words_by_ref "$1" words cword

    local i cur="" index=$COMP_POINT lead=${COMP_LINE:0:COMP_POINT}
    # Cursor not at position 0 and not leaded by just space(s)?
    if [[ $index -gt 0 && ($lead && ${lead//[[:space:]]/}) ]]; then
        cur=$COMP_LINE
        for ((i = 0; i <= cword; ++i)); do
            # Current word fits in $cur, and $cur doesn't match cword?
            while [[ ${#cur} -ge ${#words[i]} && \
                ${cur:0:${#words[i]}} != "${words[i]-}" ]]; do
                # Strip first character
                cur="${cur:1}"
                # Decrease cursor position, staying >= 0
                ((index > 0)) && ((index--))
            done

            # Does found word match cword?
            if ((i < cword)); then
                # No, cword lies further;
                local old_size=${#cur}
                cur="${cur#"${words[i]}"}"
                local new_size=${#cur}
                ((index -= old_size - new_size))
            fi
        done
        # Clear $cur if just space(s)
        [[ $cur && ! ${cur//[[:space:]]/} ]] && cur=
        # Zero $index if negative
        ((index < 0)) && index=0
    fi

    local "$2" "$3" "$4" && _upvars -a${#words[@]} $2 ${words+"${words[@]}"} \
        -v $3 "$cword" -v $4 "${cur:0:index}"
}

# Get the word to complete and optional previous words.
# This is nicer than ${COMP_WORDS[COMP_CWORD]}, since it handles cases
# where the user is completing in the middle of a word.
# (For example, if the line is "ls foobar",
# and the cursor is here -------->   ^
# Also one is able to cross over possible wordbreak characters.
# Usage: _get_comp_words_by_ref [OPTIONS] [VARNAMES]
# Available VARNAMES:
#     cur         Return cur via $cur
#     prev        Return prev via $prev
#     words       Return words via $words
#     cword       Return cword via $cword
#
# Available OPTIONS:
#     -n EXCLUDE  Characters out of $COMP_WORDBREAKS which should NOT be
#                 considered word breaks. This is useful for things like scp
#                 where we want to return host:path and not only path, so we
#                 would pass the colon (:) as -n option in this case.
#     -c VARNAME  Return cur via $VARNAME
#     -p VARNAME  Return prev via $VARNAME
#     -w VARNAME  Return words via $VARNAME
#     -i VARNAME  Return cword via $VARNAME
#
# Example usage:
#
#    $ _get_comp_words_by_ref -n : cur prev
#
_get_comp_words_by_ref()
{
    local exclude flag i OPTIND=1
    local cur cword words=()
    local upargs=() upvars=() vcur vcword vprev vwords

    while getopts "c:i:n:p:w:" flag "$@"; do
        case $flag in
            c) vcur=$OPTARG ;;
            i) vcword=$OPTARG ;;
            n) exclude=$OPTARG ;;
            p) vprev=$OPTARG ;;
            w) vwords=$OPTARG ;;
            *)
                echo "bash_completion: $FUNCNAME: usage error" >&2
                return 1
                ;;
        esac
    done
    while [[ $# -ge $OPTIND ]]; do
        case ${!OPTIND} in
            cur) vcur=cur ;;
            prev) vprev=prev ;;
            cword) vcword=cword ;;
            words) vwords=words ;;
            *)
                echo "bash_completion: $FUNCNAME: \`${!OPTIND}':" \
                    "unknown argument" >&2
                return 1
                ;;
        esac
        ((OPTIND += 1))
    done

    __get_cword_at_cursor_by_ref "${exclude-}" words cword cur

    [[ -v vcur ]] && {
        upvars+=("$vcur")
        upargs+=(-v $vcur "$cur")
    }
    [[ -v vcword ]] && {
        upvars+=("$vcword")
        upargs+=(-v $vcword "$cword")
    }
    [[ -v vprev && $cword -ge 1 ]] && {
        upvars+=("$vprev")
        upargs+=(-v $vprev "${words[cword - 1]}")
    }
    [[ -v vwords ]] && {
        upvars+=("$vwords")
        upargs+=(-a${#words[@]} $vwords ${words+"${words[@]}"})
    }

    ((${#upvars[@]})) && local "${upvars[@]}" && _upvars "${upargs[@]}"
}

# Get the word to complete.
# This is nicer than ${COMP_WORDS[COMP_CWORD]}, since it handles cases
# where the user is completing in the middle of a word.
# (For example, if the line is "ls foobar",
# and the cursor is here -------->   ^
# @param $1 string  Characters out of $COMP_WORDBREAKS which should NOT be
#     considered word breaks. This is useful for things like scp where
#     we want to return host:path and not only path, so we would pass the
#     colon (:) as $1 in this case.
# @param $2 integer  Index number of word to return, negatively offset to the
#     current word (default is 0, previous is 1), respecting the exclusions
#     given at $1.  For example, `_get_cword "=:" 1' returns the word left of
#     the current word, respecting the exclusions "=:".
# @deprecated  Use `_get_comp_words_by_ref cur' instead
# @see _get_comp_words_by_ref()
_get_cword()
{
    local LC_CTYPE=C
    local cword words
    __reassemble_comp_words_by_ref "${1-}" words cword

    # return previous word offset by $2
    if [[ ${2-} && ${2//[^0-9]/} ]]; then
        printf "%s" "${words[cword - $2]}"
    elif ((${#words[cword]} == 0 && COMP_POINT == ${#COMP_LINE})); then
        : # nothing
    else
        local i
        local cur="$COMP_LINE"
        local index="$COMP_POINT"
        for ((i = 0; i <= cword; ++i)); do
            # Current word fits in $cur, and $cur doesn't match cword?
            while [[ ${#cur} -ge ${#words[i]} && \
                ${cur:0:${#words[i]}} != "${words[i]}" ]]; do
                # Strip first character
                cur="${cur:1}"
                # Decrease cursor position, staying >= 0
                ((index > 0)) && ((index--))
            done

            # Does found word match cword?
            if ((i < cword)); then
                # No, cword lies further;
                local old_size="${#cur}"
                cur="${cur#${words[i]}}"
                local new_size="${#cur}"
                ((index -= old_size - new_size))
            fi
        done

        if [[ ${words[cword]:0:${#cur}} != "$cur" ]]; then
            # We messed up! At least return the whole word so things
            # keep working
            printf "%s" "${words[cword]}"
        else
            printf "%s" "${cur:0:index}"
        fi
    fi
} # _get_cword()

# Get word previous to the current word.
# This is a good alternative to `prev=${COMP_WORDS[COMP_CWORD-1]}' because bash4
# will properly return the previous word with respect to any given exclusions to
# COMP_WORDBREAKS.
# @deprecated  Use `_get_comp_words_by_ref cur prev' instead
# @see _get_comp_words_by_ref()
#
_get_pword()
{
    if ((COMP_CWORD >= 1)); then
        _get_cword "${@:-}" 1
    fi
}

# If the word-to-complete contains a colon (:), left-trim COMPREPLY items with
# word-to-complete.
# With a colon in COMP_WORDBREAKS, words containing
# colons are always completed as entire words if the word to complete contains
# a colon.  This function fixes this, by removing the colon-containing-prefix
# from COMPREPLY items.
# The preferred solution is to remove the colon (:) from COMP_WORDBREAKS in
# your .bashrc:
#
#    # Remove colon (:) from list of word completion separators
#    COMP_WORDBREAKS=${COMP_WORDBREAKS//:}
#
# See also: Bash FAQ - E13) Why does filename completion misbehave if a colon
# appears in the filename? - https://tiswww.case.edu/php/chet/bash/FAQ
# @param $1 current word to complete (cur)
# @modifies global array $COMPREPLY
#
__ltrim_colon_completions()
{
    if [[ $1 == *:* && $COMP_WORDBREAKS == *:* ]]; then
        # Remove colon-word prefix from COMPREPLY items
        local colon_word=${1%"${1##*:}"}
        local i=${#COMPREPLY[*]}
        while ((i-- > 0)); do
            COMPREPLY[i]=${COMPREPLY[i]#"$colon_word"}
        done
    fi
} # __ltrim_colon_completions()

# This function quotes the argument in a way so that readline dequoting
# results in the original argument.  This is necessary for at least
# `compgen' which requires its arguments quoted/escaped:
#
#     $ ls "a'b/"
#     c
#     $ compgen -f "a'b/"       # Wrong, doesn't return output
#     $ compgen -f "a\'b/"      # Good
#     a\'b/c
#
# See also:
# - https://lists.gnu.org/archive/html/bug-bash/2009-03/msg00155.html
# - https://www.mail-archive.com/bash-completion-devel@lists.alioth.debian.org/msg01944.html
# @param $1  Argument to quote
# @param $2  Name of variable to return result to
_quote_readline_by_ref()
{
    if [ -z "$1" ]; then
        # avoid quoting if empty
        printf -v $2 %s "$1"
    elif [[ $1 == \'* ]]; then
        # Leave out first character
        printf -v $2 %s "${1:1}"
    elif [[ $1 == ~* ]]; then
        # avoid escaping first ~
        printf -v $2 ~%q "${1:1}"
    else
        printf -v $2 %q "$1"
    fi

    # If result becomes quoted like this: $'string', re-evaluate in order to
    # drop the additional quoting.  See also:
    # https://www.mail-archive.com/bash-completion-devel@lists.alioth.debian.org/msg01942.html
    [[ ${!2} == \$* ]] && eval $2=${!2}
} # _quote_readline_by_ref()

# This function performs file and directory completion. It's better than
# simply using 'compgen -f', because it honours spaces in filenames.
# @param $1  If `-d', complete only on directories.  Otherwise filter/pick only
#            completions with `.$1' and the uppercase version of it as file
#            extension.
#
_filedir()
{
    local IFS=$'\n'

    _tilde "${cur-}" || return

    local -a toks
    local reset arg=${1-}

    if [[ $arg == -d ]]; then
        reset=$(shopt -po noglob)
        set -o noglob
        toks=($(compgen -d -- "${cur-}"))
        IFS=' '
        $reset
        IFS=$'\n'
    else
        local quoted
        _quote_readline_by_ref "${cur-}" quoted

        # Munge xspec to contain uppercase version too
        # https://lists.gnu.org/archive/html/bug-bash/2010-09/msg00036.html
        # news://news.gmane.io/4C940E1C.1010304@case.edu
        local xspec=${arg:+"!*.@($arg|${arg^^})"} plusdirs=()

        # Use plusdirs to get dir completions if we have a xspec; if we don't,
        # there's no need, dirs come along with other completions. Don't use
        # plusdirs quite yet if fallback is in use though, in order to not ruin
        # the fallback condition with the "plus" dirs.
        local opts=(-f -X "$xspec")
        [[ $xspec ]] && plusdirs=(-o plusdirs)
        [[ ${COMP_FILEDIR_FALLBACK-} || -z ${plusdirs-} ]] ||
            opts+=("${plusdirs[@]}")

        reset=$(shopt -po noglob)
        set -o noglob
        toks+=($(compgen "${opts[@]}" -- $quoted))
        IFS=' '
        $reset
        IFS=$'\n'

        # Try without filter if it failed to produce anything and configured to
        [[ -n ${COMP_FILEDIR_FALLBACK-} && -n $arg && ${#toks[@]} -lt 1 ]] && {
            reset=$(shopt -po noglob)
            set -o noglob
            toks+=($(compgen -f ${plusdirs+"${plusdirs[@]}"} -- $quoted))
            IFS=' '
            $reset
            IFS=$'\n'
        }
    fi

    if ((${#toks[@]} != 0)); then
        # 2>/dev/null for direct invocation, e.g. in the _filedir unit test
        compopt -o filenames 2>/dev/null
        COMPREPLY+=("${toks[@]}")
    fi
} # _filedir()

# This function splits $cur=--foo=bar into $prev=--foo, $cur=bar, making it
# easier to support both "--foo bar" and "--foo=bar" style completions.
# `=' should have been removed from COMP_WORDBREAKS when setting $cur for
# this to be useful.
# Returns 0 if current option was split, 1 otherwise.
#
_split_longopt()
{
    if [[ $cur == --?*=* ]]; then
        # Cut also backslash before '=' in case it ended up there
        # for some reason.
        prev="${cur%%?(\\)=*}"
        cur="${cur#*=}"
        return 0
    fi

    return 1
}

# Complete variables.
# @return  True (0) if variables were completed,
#          False (> 0) if not.
_variables()
{
    if [[ $cur =~ ^(\$(\{[!#]?)?)([A-Za-z0-9_]*)$ ]]; then
        # Completing $var / ${var / ${!var / ${#var
        if [[ $cur == '${'* ]]; then
            local arrs vars
            vars=($(compgen -A variable -P ${BASH_REMATCH[1]} -S '}' -- ${BASH_REMATCH[3]}))
            arrs=($(compgen -A arrayvar -P ${BASH_REMATCH[1]} -S '[' -- ${BASH_REMATCH[3]}))
            if ((${#vars[@]} == 1 && ${#arrs[@]} != 0)); then
                # Complete ${arr with ${array[ if there is only one match, and that match is an array variable
                compopt -o nospace
                COMPREPLY+=(${arrs[*]})
            else
                # Complete ${var with ${variable}
                COMPREPLY+=(${vars[*]})
            fi
        else
            # Complete $var with $variable
            COMPREPLY+=($(compgen -A variable -P '$' -- "${BASH_REMATCH[3]}"))
        fi
        return 0
    elif [[ $cur =~ ^(\$\{[#!]?)([A-Za-z0-9_]*)\[([^]]*)$ ]]; then
        # Complete ${array[i with ${array[idx]}
        local IFS=$'\n'
        COMPREPLY+=($(compgen -W '$(printf %s\\n "${!'${BASH_REMATCH[2]}'[@]}")' \
            -P "${BASH_REMATCH[1]}${BASH_REMATCH[2]}[" -S ']}' -- "${BASH_REMATCH[3]}"))
        # Complete ${arr[@ and ${arr[*
        if [[ ${BASH_REMATCH[3]} == [@*] ]]; then
            COMPREPLY+=("${BASH_REMATCH[1]}${BASH_REMATCH[2]}[${BASH_REMATCH[3]}]}")
        fi
        __ltrim_colon_completions "$cur" # array indexes may have colons
        return 0
    elif [[ $cur =~ ^\$\{[#!]?[A-Za-z0-9_]*\[.*\]$ ]]; then
        # Complete ${array[idx] with ${array[idx]}
        COMPREPLY+=("$cur}")
        __ltrim_colon_completions "$cur"
        return 0
    fi
    return 1
}

# Complete assignment of various known environment variables.
# The word to be completed is expected to contain the entire
# assignment, including the variable name and the "=". See related
# parameters to _init_completion.
#
# @param  $1 variable assignment to be completed
# @return True (0) if variable value completion was attempted,
#         False (> 0) if not.
_variable_assignments()
{
    local cur=${1-}

    if [[ $cur =~ ^([A-Za-z_][A-Za-z0-9_]*)=(.*)$ ]]; then
        prev=${BASH_REMATCH[1]}
        cur=${BASH_REMATCH[2]}
    else
        return 1
    fi

    case $prev in
        TZ)
            cur=/usr/share/zoneinfo/$cur
            _filedir
            for i in "${!COMPREPLY[@]}"; do
                if [[ ${COMPREPLY[i]} == *.tab ]]; then
                    unset 'COMPREPLY[i]'
                    continue
                elif [[ -d ${COMPREPLY[i]} ]]; then
                    COMPREPLY[i]+=/
                    compopt -o nospace
                fi
                COMPREPLY[i]=${COMPREPLY[i]#/usr/share/zoneinfo/}
            done
            ;;
        TERM)
            _terms
            ;;
        LANG | LC_*)
            COMPREPLY=($(compgen -W '$(locale -a 2>/dev/null)' \
                -- "$cur"))
            ;;
        *)
            _variables && return 0
            _filedir
            ;;
    esac

    return 0
}

# Initialize completion and deal with various general things: do file
# and variable completion where appropriate, and adjust prev, words,
# and cword as if no redirections exist so that completions do not
# need to deal with them.  Before calling this function, make sure
# cur, prev, words, and cword are local, ditto split if you use -s.
#
# Options:
#     -n EXCLUDE  Passed to _get_comp_words_by_ref -n with redirection chars
#     -e XSPEC    Passed to _filedir as first arg for stderr redirections
#     -o XSPEC    Passed to _filedir as first arg for other output redirections
#     -i XSPEC    Passed to _filedir as first arg for stdin redirections
#     -s          Split long options with _split_longopt, implies -n =
# @return  True (0) if completion needs further processing,
#          False (> 0) no further processing is necessary.
#
_init_completion()
{
    local exclude="" flag outx errx inx OPTIND=1

    while getopts "n:e:o:i:s" flag "$@"; do
        case $flag in
            n) exclude+=$OPTARG ;;
            e) errx=$OPTARG ;;
            o) outx=$OPTARG ;;
            i) inx=$OPTARG ;;
            s)
                split=false
                exclude+==
                ;;
            *)
                echo "bash_completion: $FUNCNAME: usage error" >&2
                return 1
                ;;
        esac
    done

    COMPREPLY=()
    local redir="@(?([0-9])<|?([0-9&])>?(>)|>&)"
    _get_comp_words_by_ref -n "$exclude<>&" cur prev words cword

    # Complete variable names.
    _variables && return 1

    # Complete on files if current is a redirect possibly followed by a
    # filename, e.g. ">foo", or previous is a "bare" redirect, e.g. ">".
    # shellcheck disable=SC2053
    if [[ $cur == $redir* || ${prev-} == $redir ]]; then
        local xspec
        case $cur in
            2'>'*) xspec=${errx-} ;;
            *'>'*) xspec=${outx-} ;;
            *'<'*) xspec=${inx-} ;;
            *)
                case $prev in
                    2'>'*) xspec=${errx-} ;;
                    *'>'*) xspec=${outx-} ;;
                    *'<'*) xspec=${inx-} ;;
                esac
                ;;
        esac
        cur="${cur##$redir}"
        _filedir $xspec
        return 1
    fi

    # Remove all redirections so completions don't have to deal with them.
    local i skip
    for ((i = 1; i < ${#words[@]}; )); do
        if [[ ${words[i]} == $redir* ]]; then
            # If "bare" redirect, remove also the next word (skip=2).
            # shellcheck disable=SC2053
            [[ ${words[i]} == $redir ]] && skip=2 || skip=1
            words=("${words[@]:0:i}" "${words[@]:i+skip}")
            ((i <= cword)) && ((cword -= skip))
        else
            ((i++))
        fi
    done

    ((cword <= 0)) && return 1
    prev=${words[cword - 1]}

    [[ ${split-} ]] && _split_longopt && split=true

    return 0
}

# Helper function for _parse_help and _parse_usage.
__parse_options()
{
    local option option2 i IFS=$' \t\n,/|'

    # Take first found long option, or first one (short) if not found.
    option=
    local -a array=($1)
    for i in "${array[@]}"; do
        case "$i" in
            ---*) break ;;
            --?*)
                option=$i
                break
                ;;
            -?*) [[ $option ]] || option=$i ;;
            *) break ;;
        esac
    done
    [[ $option ]] || return 0

    IFS=$' \t\n' # affects parsing of the regexps below...

    # Expand --[no]foo to --foo and --nofoo etc
    if [[ $option =~ (\[((no|dont)-?)\]). ]]; then
        option2=${option/"${BASH_REMATCH[1]}"/}
        option2=${option2%%[<{().[]*}
        printf '%s\n' "${option2/=*/=}"
        option=${option/"${BASH_REMATCH[1]}"/"${BASH_REMATCH[2]}"}
    fi

    option=${option%%[<{().[]*}
    printf '%s\n' "${option/=*/=}"
}

# Parse GNU style help output of the given command.
# @param $1  command; if "-", read from stdin and ignore rest of args
# @param $2  command options (default: --help)
#
_parse_help()
{
    eval local cmd="$(quote "$1")"
    local line
    {
        case $cmd in
            -) cat ;;
            *) LC_ALL=C "$(dequote "$cmd")" ${2:---help} 2>&1 ;;
        esac
    } |
        while read -r line; do

            [[ $line == *([[:blank:]])-* ]] || continue
            # transform "-f FOO, --foo=FOO" to "-f , --foo=FOO" etc
            while [[ $line =~ \
                ((^|[^-])-[A-Za-z0-9?][[:space:]]+)\[?[A-Z0-9]+([,_-]+[A-Z0-9]+)?(\.\.+)?\]? ]]; do
                line=${line/"${BASH_REMATCH[0]}"/"${BASH_REMATCH[1]}"}
            done
            __parse_options "${line// or /, }"

        done
}

# Parse BSD style usage output (options in brackets) of the given command.
# @param $1  command; if "-", read from stdin and ignore rest of args
# @param $2  command options (default: --usage)
#
_parse_usage()
{
    eval local cmd="$(quote "$1")"
    local line match option i char
    {
        case $cmd in
            -) cat ;;
            *) LC_ALL=C "$(dequote "$cmd")" ${2:---usage} 2>&1 ;;
        esac
    } |
        while read -r line; do

            while [[ $line =~ \[[[:space:]]*(-[^]]+)[[:space:]]*\] ]]; do
                match=${BASH_REMATCH[0]}
                option=${BASH_REMATCH[1]}
                case $option in
                    -?(\[)+([a-zA-Z0-9?]))
                        # Treat as bundled short options
                        for ((i = 1; i < ${#option}; i++)); do
                            char=${option:i:1}
                            [[ $char != '[' ]] && printf '%s\n' -$char
                        done
                        ;;
                    *)
                        __parse_options "$option"
                        ;;
                esac
                line=${line#*"$match"}
            done

        done
}

# This function completes on signal names (minus the SIG prefix)
# @param $1 prefix
_signals()
{
    local -a sigs=($(compgen -P "${1-}" -A signal "SIG${cur#${1-}}"))
    COMPREPLY+=("${sigs[@]/#${1-}SIG/${1-}}")
}

# This function completes on known mac addresses
#
_mac_addresses()
{
    local re='\([A-Fa-f0-9]\{2\}:\)\{5\}[A-Fa-f0-9]\{2\}'
    local PATH="$PATH:/sbin:/usr/sbin"

    # Local interfaces
    # - ifconfig on Linux: HWaddr or ether
    # - ifconfig on FreeBSD: ether
    # - ip link: link/ether
    COMPREPLY+=($(
        {
            LC_ALL=C ifconfig -a || ip link show
        } 2>/dev/null | command sed -ne \
            "s/.*[[:space:]]HWaddr[[:space:]]\{1,\}\($re\)[[:space:]].*/\1/p" -ne \
            "s/.*[[:space:]]HWaddr[[:space:]]\{1,\}\($re\)[[:space:]]*$/\1/p" -ne \
            "s|.*[[:space:]]\(link/\)\{0,1\}ether[[:space:]]\{1,\}\($re\)[[:space:]].*|\2|p" -ne \
            "s|.*[[:space:]]\(link/\)\{0,1\}ether[[:space:]]\{1,\}\($re\)[[:space:]]*$|\2|p"
    ))

    # ARP cache
    COMPREPLY+=($({
        arp -an || ip neigh show
    } 2>/dev/null | command sed -ne \
        "s/.*[[:space:]]\($re\)[[:space:]].*/\1/p" -ne \
        "s/.*[[:space:]]\($re\)[[:space:]]*$/\1/p"))

    # /etc/ethers
    COMPREPLY+=($(command sed -ne \
        "s/^[[:space:]]*\($re\)[[:space:]].*/\1/p" /etc/ethers 2>/dev/null))

    COMPREPLY=($(compgen -W '${COMPREPLY[@]}' -- "$cur"))
    __ltrim_colon_completions "$cur"
}

# This function completes on configured network interfaces
#
_configured_interfaces()
{
    if [[ -f /etc/debian_version ]]; then
        # Debian system
        COMPREPLY=($(compgen -W "$(command sed -ne 's|^iface \([^ ]\{1,\}\).*$|\1|p' \
            /etc/network/interfaces /etc/network/interfaces.d/* 2>/dev/null)" \
            -- "$cur"))
    elif [[ -f /etc/SuSE-release ]]; then
        # SuSE system
        COMPREPLY=($(compgen -W "$(printf '%s\n' \
            /etc/sysconfig/network/ifcfg-* |
            command sed -ne 's|.*ifcfg-\([^*].*\)$|\1|p')" -- "$cur"))
    elif [[ -f /etc/pld-release ]]; then
        # PLD Linux
        COMPREPLY=($(compgen -W "$(command ls -B \
            /etc/sysconfig/interfaces |
            command sed -ne 's|.*ifcfg-\([^*].*\)$|\1|p')" -- "$cur"))
    else
        # Assume Red Hat
        COMPREPLY=($(compgen -W "$(printf '%s\n' \
            /etc/sysconfig/network-scripts/ifcfg-* |
            command sed -ne 's|.*ifcfg-\([^*].*\)$|\1|p')" -- "$cur"))
    fi
}

# Local IP addresses.
# -4: IPv4 addresses only (default)
# -6: IPv6 addresses only
# -a: All addresses
#
_ip_addresses()
{
    local n
    case ${1-} in
        -a) n='6\?' ;;
        -6) n='6' ;;
        *) n= ;;
    esac
    local PATH=$PATH:/sbin
    local addrs=$({
        LC_ALL=C ifconfig -a || ip addr show
    } 2>/dev/null |
        command sed -e 's/[[:space:]]addr:/ /' -ne \
            "s|.*inet${n}[[:space:]]\{1,\}\([^[:space:]/]*\).*|\1|p")
    COMPREPLY+=($(compgen -W "$addrs" -- "${cur-}"))
}

# This function completes on available kernels
#
_kernel_versions()
{
    COMPREPLY=($(compgen -W '$(command ls /lib/modules)' -- "$cur"))
}

# This function completes on all available network interfaces
# -a: restrict to active interfaces only
# -w: restrict to wireless interfaces only
#
_available_interfaces()
{
    local PATH=$PATH:/sbin

    COMPREPLY=($({
        if [[ ${1:-} == -w ]]; then
            iwconfig
        elif [[ ${1:-} == -a ]]; then
            ifconfig || ip link show up
        else
            ifconfig -a || ip link show
        fi
    } 2>/dev/null | awk \
        '/^[^ \t]/ { if ($1 ~ /^[0-9]+:/) { print $2 } else { print $1 } }'))

    COMPREPLY=($(compgen -W '${COMPREPLY[@]/%[[:punct:]]/}' -- "$cur"))
}

# Echo number of CPUs, falling back to 1 on failure.
_ncpus()
{
    local var=NPROCESSORS_ONLN
    [[ $OSTYPE == *linux* ]] && var=_$var
    local n=$(getconf $var 2>/dev/null)
    printf %s ${n:-1}
}

# Perform tilde (~) completion
# @return  True (0) if completion needs further processing,
#          False (> 0) if tilde is followed by a valid username, completions
#          are put in COMPREPLY and no further processing is necessary.
_tilde()
{
    local result=0
    if [[ ${1-} == \~* && $1 != */* ]]; then
        # Try generate ~username completions
        COMPREPLY=($(compgen -P '~' -u -- "${1#\~}"))
        result=${#COMPREPLY[@]}
        # 2>/dev/null for direct invocation, e.g. in the _tilde unit test
        ((result > 0)) && compopt -o filenames 2>/dev/null
    fi
    return $result
}

# Expand variable starting with tilde (~)
# We want to expand ~foo/... to /home/foo/... to avoid problems when
# word-to-complete starting with a tilde is fed to commands and ending up
# quoted instead of expanded.
# Only the first portion of the variable from the tilde up to the first slash
# (~../) is expanded.  The remainder of the variable, containing for example
# a dollar sign variable ($) or asterisk (*) is not expanded.
# Example usage:
#
#    $ v="~"; __expand_tilde_by_ref v; echo "$v"
#
# Example output:
#
#       v                  output
#    --------         ----------------
#    ~                /home/user
#    ~foo/bar         /home/foo/bar
#    ~foo/$HOME       /home/foo/$HOME
#    ~foo/a  b        /home/foo/a  b
#    ~foo/*           /home/foo/*
#
# @param $1  Name of variable (not the value of the variable) to expand
__expand_tilde_by_ref()
{
    if [[ ${!1-} == \~* ]]; then
        eval $1="$(printf ~%q "${!1#\~}")"
    fi
} # __expand_tilde_by_ref()

# This function expands tildes in pathnames
#
_expand()
{
    # Expand ~username type directory specifications.  We want to expand
    # ~foo/... to /home/foo/... to avoid problems when $cur starting with
    # a tilde is fed to commands and ending up quoted instead of expanded.

    case ${cur-} in
        ~*/*)
            __expand_tilde_by_ref cur
            ;;
        ~*)
            _tilde "$cur" ||
                eval COMPREPLY[0]="$(printf ~%q "${COMPREPLY[0]#\~}")"
            return ${#COMPREPLY[@]}
            ;;
    esac
}

# Process ID related functions.
# for AIX and Solaris we use X/Open syntax, BSD for others.
if [[ $OSTYPE == *@(solaris|aix)* ]]; then
    # This function completes on process IDs.
    _pids()
    {
        COMPREPLY=($(compgen -W '$(command ps -efo pid | command sed 1d)' -- "$cur"))
    }

    _pgids()
    {
        COMPREPLY=($(compgen -W '$(command ps -efo pgid | command sed 1d)' -- "$cur"))
    }
    _pnames()
    {
        COMPREPLY=($(compgen -X '<defunct>' -W '$(command ps -efo comm | \
        command sed -e 1d -e "s:.*/::" -e "s/^-//" | sort -u)' -- "$cur"))
    }
else
    _pids()
    {
        COMPREPLY=($(compgen -W '$(command ps axo pid=)' -- "$cur"))
    }
    _pgids()
    {
        COMPREPLY=($(compgen -W '$(command ps axo pgid=)' -- "$cur"))
    }
    # @param $1 if -s, don't try to avoid truncated command names
    _pnames()
    {
        local -a procs
        if [[ ${1-} == -s ]]; then
            procs=($(command ps axo comm | command sed -e 1d))
        else
            local line i=-1 ifs=$IFS
            IFS=$'\n'
            local -a psout=($(command ps axo command=))
            IFS=$ifs
            for line in "${psout[@]}"; do
                if ((i == -1)); then
                    # First line, see if it has COMMAND column header. For example
                    # the busybox ps does that, i.e. doesn't respect axo command=
                    if [[ $line =~ ^(.*[[:space:]])COMMAND([[:space:]]|$) ]]; then
                        # It does; store its index.
                        i=${#BASH_REMATCH[1]}
                    else
                        # Nope, fall through to "regular axo command=" parsing.
                        break
                    fi
                else
                    #
                    line=${line:i}   # take command starting from found index
                    line=${line%% *} # trim arguments
                    procs+=($line)
                fi
            done
            if ((i == -1)); then
                # Regular axo command= parsing
                for line in "${psout[@]}"; do
                    if [[ $line =~ ^[[(](.+)[])]$ ]]; then
                        procs+=(${BASH_REMATCH[1]})
                    else
                        line=${line%% *}      # trim arguments
                        line=${line##@(*/|-)} # trim leading path and -
                        procs+=($line)
                    fi
                done
            fi
        fi
        COMPREPLY=($(compgen -X "<defunct>" -W '${procs[@]}' -- "$cur"))
    }
fi

# This function completes on user IDs
#
_uids()
{
    if type getent &>/dev/null; then
        COMPREPLY=($(compgen -W '$(getent passwd | cut -d: -f3)' -- "$cur"))
    elif type perl &>/dev/null; then
        COMPREPLY=($(compgen -W '$(perl -e '"'"'while (($uid) = (getpwent)[2]) { print $uid . "\n" }'"'"')' -- "$cur"))
    else
        # make do with /etc/passwd
        COMPREPLY=($(compgen -W '$(cut -d: -f3 /etc/passwd)' -- "$cur"))
    fi
}

# This function completes on group IDs
#
_gids()
{
    if type getent &>/dev/null; then
        COMPREPLY=($(compgen -W '$(getent group | cut -d: -f3)' -- "$cur"))
    elif type perl &>/dev/null; then
        COMPREPLY=($(compgen -W '$(perl -e '"'"'while (($gid) = (getgrent)[2]) { print $gid . "\n" }'"'"')' -- "$cur"))
    else
        # make do with /etc/group
        COMPREPLY=($(compgen -W '$(cut -d: -f3 /etc/group)' -- "$cur"))
    fi
}

# Glob for matching various backup files.
#
_backup_glob='@(#*#|*@(~|.@(bak|orig|rej|swp|dpkg*|rpm@(orig|new|save))))'

# Complete on xinetd services
#
_xinetd_services()
{
    local xinetddir=${BASHCOMP_XINETDDIR:-/etc/xinetd.d}
    if [[ -d $xinetddir ]]; then
        local IFS=$' \t\n' reset=$(shopt -p nullglob)
        shopt -s nullglob
        local -a svcs=($(printf '%s\n' $xinetddir/!($_backup_glob)))
        $reset
        ((!${#svcs[@]})) ||
            COMPREPLY+=($(compgen -W '${svcs[@]#$xinetddir/}' -- "${cur-}"))
    fi
}

# This function completes on services
#
_services()
{
    local sysvdirs
    _sysvdirs

    local IFS=$' \t\n' reset=$(shopt -p nullglob)
    shopt -s nullglob
    COMPREPLY=(
        $(printf '%s\n' ${sysvdirs[0]}/!($_backup_glob|functions|README)))
    $reset

    COMPREPLY+=($({
        systemctl list-units --full --all ||
            systemctl list-unit-files
    } 2>/dev/null |
        awk '$1 ~ /\.service$/ { sub("\\.service$", "", $1); print $1 }'))

    if [[ -x /sbin/upstart-udev-bridge ]]; then
        COMPREPLY+=($(initctl list 2>/dev/null | cut -d' ' -f1))
    fi

    COMPREPLY=($(compgen -W '${COMPREPLY[@]#${sysvdirs[0]}/}' -- "$cur"))
}

# This completes on a list of all available service scripts for the
# 'service' command and/or the SysV init.d directory, followed by
# that script's available commands
#
_service()
{
    local cur prev words cword
    _init_completion || return

    # don't complete past 2nd token
    ((cword > 2)) && return

    if [[ $cword -eq 1 && $prev == ?(*/)service ]]; then
        _services
        [[ -e /etc/mandrake-release ]] && _xinetd_services
    else
        local sysvdirs
        _sysvdirs
        COMPREPLY=($(compgen -W '`command sed -e "y/|/ /" \
            -ne "s/^.*\(U\|msg_u\)sage.*{\(.*\)}.*$/\2/p" \
            ${sysvdirs[0]}/${prev##*/} 2>/dev/null` start stop' -- "$cur"))
    fi
} &&
    complete -F _service service
_sysvdirs
for svcdir in "${sysvdirs[@]}"; do
    for svc in $svcdir/!($_backup_glob); do
        [[ -x $svc ]] && complete -F _service $svc
    done
done
unset svc svcdir sysvdirs

# This function completes on modules
#
_modules()
{
    local modpath
    modpath=/lib/modules/$1
    COMPREPLY=($(compgen -W "$(command ls -RL $modpath 2>/dev/null |
        command sed -ne 's/^\(.*\)\.k\{0,1\}o\(\.[gx]z\)\{0,1\}$/\1/p')" -- "$cur"))
}

# This function completes on installed modules
#
_installed_modules()
{
    COMPREPLY=($(compgen -W "$(PATH="$PATH:/sbin" lsmod |
        awk '{if (NR != 1) print $1}')" -- "$1"))
}

# This function completes on user or user:group format; as for chown and cpio.
#
# The : must be added manually; it will only complete usernames initially.
# The legacy user.group format is not supported.
#
# @param $1  If -u, only return users/groups the user has access to in
#            context of current completion.
_usergroup()
{
    if [[ $cur == *\\\\* || $cur == *:*:* ]]; then
        # Give up early on if something seems horribly wrong.
        return
    elif [[ $cur == *\\:* ]]; then
        # Completing group after 'user\:gr<TAB>'.
        # Reply with a list of groups prefixed with 'user:', readline will
        # escape to the colon.
        local prefix
        prefix=${cur%%*([^:])}
        prefix=${prefix//\\/}
        local mycur="${cur#*[:]}"
        if [[ ${1-} == -u ]]; then
            _allowed_groups "$mycur"
        else
            local IFS=$'\n'
            COMPREPLY=($(compgen -g -- "$mycur"))
        fi
        COMPREPLY=($(compgen -P "$prefix" -W "${COMPREPLY[@]}"))
    elif [[ $cur == *:* ]]; then
        # Completing group after 'user:gr<TAB>'.
        # Reply with a list of unprefixed groups since readline with split on :
        # and only replace the 'gr' part
        local mycur="${cur#*:}"
        if [[ ${1-} == -u ]]; then
            _allowed_groups "$mycur"
        else
            local IFS=$'\n'
            COMPREPLY=($(compgen -g -- "$mycur"))
        fi
    else
        # Completing a partial 'usernam<TAB>'.
        #
        # Don't suffix with a : because readline will escape it and add a
        # slash. It's better to complete into 'chown username ' than 'chown
        # username\:'.
        if [[ ${1-} == -u ]]; then
            _allowed_users "$cur"
        else
            local IFS=$'\n'
            COMPREPLY=($(compgen -u -- "$cur"))
        fi
    fi
}

_allowed_users()
{
    if _complete_as_root; then
        local IFS=$'\n'
        COMPREPLY=($(compgen -u -- "${1:-$cur}"))
    else
        local IFS=$'\n '
        COMPREPLY=($(compgen -W \
            "$(id -un 2>/dev/null || whoami 2>/dev/null)" -- "${1:-$cur}"))
    fi
}

_allowed_groups()
{
    if _complete_as_root; then
        local IFS=$'\n'
        COMPREPLY=($(compgen -g -- "$1"))
    else
        local IFS=$'\n '
        COMPREPLY=($(compgen -W \
            "$(id -Gn 2>/dev/null || groups 2>/dev/null)" -- "$1"))
    fi
}

# This function completes on valid shells
#
_shells()
{
    local shell rest
    while read -r shell rest; do
        [[ $shell == /* && $shell == "$cur"* ]] && COMPREPLY+=($shell)
    done 2>/dev/null </etc/shells
}

# This function completes on valid filesystem types
#
_fstypes()
{
    local fss

    if [[ -e /proc/filesystems ]]; then
        # Linux
        fss="$(cut -d$'\t' -f2 /proc/filesystems)
             $(awk '! /\*/ { print $NF }' /etc/filesystems 2>/dev/null)"
    else
        # Generic
        fss="$(awk '/^[ \t]*[^#]/ { print $3 }' /etc/fstab 2>/dev/null)
             $(awk '/^[ \t]*[^#]/ { print $3 }' /etc/mnttab 2>/dev/null)
             $(awk '/^[ \t]*[^#]/ { print $4 }' /etc/vfstab 2>/dev/null)
             $(awk '{ print $1 }' /etc/dfs/fstypes 2>/dev/null)
             $([[ -d /etc/fs ]] && command ls /etc/fs)"
    fi

    [[ -n $fss ]] && COMPREPLY+=($(compgen -W "$fss" -- "$cur"))
}

# Get real command.
# - arg: $1  Command
# - stdout:  Filename of command in PATH with possible symbolic links resolved.
#            Empty string if command not found.
# - return:  True (0) if command found, False (> 0) if not.
_realcommand()
{
    type -P "$1" >/dev/null && {
        if type -p realpath >/dev/null; then
            realpath "$(type -P "$1")"
        elif type -p greadlink >/dev/null; then
            greadlink -f "$(type -P "$1")"
        elif type -p readlink >/dev/null; then
            readlink -f "$(type -P "$1")"
        else
            type -P "$1"
        fi
    }
}

# This function returns the first argument, excluding options
# @param $1 chars  Characters out of $COMP_WORDBREAKS which should
#     NOT be considered word breaks. See __reassemble_comp_words_by_ref.
_get_first_arg()
{
    local i

    arg=
    for ((i = 1; i < COMP_CWORD; i++)); do
        if [[ ${COMP_WORDS[i]} != -* ]]; then
            arg=${COMP_WORDS[i]}
            break
        fi
    done
}

# This function counts the number of args, excluding options
# @param $1 chars  Characters out of $COMP_WORDBREAKS which should
#     NOT be considered word breaks. See __reassemble_comp_words_by_ref.
# @param $2 glob   Options whose following argument should not be counted
# @param $3 glob   Options that should be counted as args
_count_args()
{
    local i cword words
    __reassemble_comp_words_by_ref "${1-}" words cword

    args=1
    for ((i = 1; i < cword; i++)); do
        # shellcheck disable=SC2053
        if [[ ${words[i]} != -* && ${words[i - 1]} != ${2-} || \
            ${words[i]} == ${3-} ]]; then
            ((args++))
        fi
    done
}

# This function completes on PCI IDs
#
_pci_ids()
{
    COMPREPLY+=($(compgen -W \
        "$(PATH="$PATH:/sbin" lspci -n | awk '{print $3}')" -- "$cur"))
}

# This function completes on USB IDs
#
_usb_ids()
{
    COMPREPLY+=($(compgen -W \
        "$(PATH="$PATH:/sbin" lsusb | awk '{print $6}')" -- "$cur"))
}

# CD device names
_cd_devices()
{
    COMPREPLY+=($(compgen -f -d -X "!*/?([amrs])cd*" -- "${cur:-/dev/}"))
}

# DVD device names
_dvd_devices()
{
    COMPREPLY+=($(compgen -f -d -X "!*/?(r)dvd*" -- "${cur:-/dev/}"))
}

# TERM environment variable values
_terms()
{
    COMPREPLY+=($(compgen -W "$({
        command sed -ne 's/^\([^[:space:]#|]\{2,\}\)|.*/\1/p' /etc/termcap
        {
            toe -a || toe
        } | awk '{ print $1 }'
        find /{etc,lib,usr/lib,usr/share}/terminfo/? -type f -maxdepth 1 |
            awk -F/ '{ print $NF }'
    } 2>/dev/null)" -- "$cur"))
}

_bashcomp_try_faketty()
{
    if type unbuffer &>/dev/null; then
        unbuffer -p "$@"
    elif script --version 2>&1 | command grep -qF util-linux; then
        # BSD and Solaris "script" do not seem to have required features
        script -qaefc "$*" /dev/null
    else
        "$@" # no can do, fallback
    fi
}

# a little help for FreeBSD ports users
[[ $OSTYPE == *freebsd* ]] && complete -W 'index search fetch fetch-list
    extract patch configure build install reinstall deinstall clean
    clean-depends kernel buildworld' make

# This function provides simple user@host completion
#
_user_at_host()
{
    local cur prev words cword
    _init_completion -n : || return

    if [[ $cur == *@* ]]; then
        _known_hosts_real "$cur"
    else
        COMPREPLY=($(compgen -u -S @ -- "$cur"))
        compopt -o nospace
    fi
}
shopt -u hostcomplete && complete -F _user_at_host talk ytalk finger

# NOTE: Using this function as a helper function is deprecated.  Use
#       `_known_hosts_real' instead.
_known_hosts()
{
    local cur prev words cword
    _init_completion -n : || return

    # NOTE: Using `_known_hosts' as a helper function and passing options
    #       to `_known_hosts' is deprecated: Use `_known_hosts_real' instead.
    local options
    [[ ${1-} == -a || ${2-} == -a ]] && options=-a
    [[ ${1-} == -c || ${2-} == -c ]] && options+=" -c"
    _known_hosts_real ${options-} -- "$cur"
} # _known_hosts()

# Helper function to locate ssh included files in configs
# This function looks for the "Include" keyword in ssh config files and
# includes them recursively, adding each result to the config variable.
_included_ssh_config_files()
{
    (($# < 1)) &&
        echo "bash_completion: $FUNCNAME: missing mandatory argument CONFIG" >&2
    local configfile i f
    configfile=$1

    local reset=$(shopt -po noglob)
    set -o noglob
    local included=($(command sed -ne 's/^[[:blank:]]*[Ii][Nn][Cc][Ll][Uu][Dd][Ee][[:blank:]]\(.*\)$/\1/p' "${configfile}"))
    $reset

    [[ ${included-} ]] || return
    for i in "${included[@]}"; do
        # Check the origin of $configfile to complete relative included paths on included
        # files according to ssh_config(5):
        #  "[...] Files without absolute paths are assumed to be in ~/.ssh if included in a user
        #   configuration file or /etc/ssh if included from the system configuration file.[...]"
        if ! [[ $i =~ ^\~.*|^\/.* ]]; then
            if [[ $configfile =~ ^\/etc\/ssh.* ]]; then
                i="/etc/ssh/$i"
            else
                i="$HOME/.ssh/$i"
            fi
        fi
        __expand_tilde_by_ref i
        # In case the expanded variable contains multiple paths
        set +o noglob
        for f in $i; do
            if [[ -r $f ]]; then
                config+=("$f")
                # The Included file is processed to look for Included files in itself
                _included_ssh_config_files $f
            fi
        done
        $reset
    done
} # _included_ssh_config_files()

# Helper function for completing _known_hosts.
# This function performs host completion based on ssh's config and known_hosts
# files, as well as hostnames reported by avahi-browse if
# COMP_KNOWN_HOSTS_WITH_AVAHI is set to a non-empty value.  Also hosts from
# HOSTFILE (compgen -A hostname) are added, unless
# COMP_KNOWN_HOSTS_WITH_HOSTFILE is set to an empty value.
# Usage: _known_hosts_real [OPTIONS] CWORD
# Options:  -a             Use aliases from ssh config files
#           -c             Use `:' suffix
#           -F configfile  Use `configfile' for configuration settings
#           -p PREFIX      Use PREFIX
#           -4             Filter IPv6 addresses from results
#           -6             Filter IPv4 addresses from results
# Return: Completions, starting with CWORD, are added to COMPREPLY[]
_known_hosts_real()
{
    local configfile flag prefix="" ifs=$IFS
    local cur suffix="" aliases i host ipv4 ipv6
    local -a kh tmpkh=() khd=() config=()

    # TODO remove trailing %foo from entries

    local OPTIND=1
    while getopts "ac46F:p:" flag "$@"; do
        case $flag in
            a) aliases='yes' ;;
            c) suffix=':' ;;
            F) configfile=$OPTARG ;;
            p) prefix=$OPTARG ;;
            4) ipv4=1 ;;
            6) ipv6=1 ;;
            *)
                echo "bash_completion: $FUNCNAME: usage error" >&2
                return 1
                ;;
        esac
    done
    if (($# < OPTIND)); then
        echo "bash_completion: $FUNCNAME: missing mandatory argument CWORD" >&2
        return 1
    fi
    cur=${!OPTIND}
    ((OPTIND += 1))
    if (($# >= OPTIND)); then
        echo "bash_completion: $FUNCNAME($*): unprocessed arguments:" \
            "$(while (($# >= OPTIND)); do
                printf '%s ' ${!OPTIND}
                shift
            done)" >&2
        return 1
    fi

    [[ $cur == *@* ]] && prefix=$prefix${cur%@*}@ && cur=${cur#*@}
    kh=()

    # ssh config files
    if [[ -v configfile ]]; then
        [[ -r $configfile ]] && config+=("$configfile")
    else
        for i in /etc/ssh/ssh_config ~/.ssh/config ~/.ssh2/config; do
            [[ -r $i ]] && config+=("$i")
        done
    fi

    local reset=$(shopt -po noglob)
    set -o noglob

    # "Include" keyword in ssh config files
    if ((${#config[@]} > 0)); then
        for i in "${config[@]}"; do
            _included_ssh_config_files "$i"
        done
    fi

    # Known hosts files from configs
    if ((${#config[@]} > 0)); then
        local IFS=$'\n'
        # expand paths (if present) to global and user known hosts files
        # TODO(?): try to make known hosts files with more than one consecutive
        #          spaces in their name work (watch out for ~ expansion
        #          breakage! Alioth#311595)
        tmpkh=($(awk 'sub("^[ \t]*([Gg][Ll][Oo][Bb][Aa][Ll]|[Uu][Ss][Ee][Rr])[Kk][Nn][Oo][Ww][Nn][Hh][Oo][Ss][Tt][Ss][Ff][Ii][Ll][Ee][ \t]+", "") { print $0 }' "${config[@]}" | sort -u))
        IFS=$ifs
    fi
    if ((${#tmpkh[@]} != 0)); then
        local j
        for i in "${tmpkh[@]}"; do
            # First deal with quoted entries...
            while [[ $i =~ ^([^\"]*)\"([^\"]*)\"(.*)$ ]]; do
                i=${BASH_REMATCH[1]}${BASH_REMATCH[3]}
                j=${BASH_REMATCH[2]}
                __expand_tilde_by_ref j # Eval/expand possible `~' or `~user'
                [[ -r $j ]] && kh+=("$j")
            done
            # ...and then the rest.
            for j in $i; do
                __expand_tilde_by_ref j # Eval/expand possible `~' or `~user'
                [[ -r $j ]] && kh+=("$j")
            done
        done
    fi

    if [[ ! -v configfile ]]; then
        # Global and user known_hosts files
        for i in /etc/ssh/ssh_known_hosts /etc/ssh/ssh_known_hosts2 \
            /etc/known_hosts /etc/known_hosts2 ~/.ssh/known_hosts \
            ~/.ssh/known_hosts2; do
            [[ -r $i ]] && kh+=("$i")
        done
        for i in /etc/ssh2/knownhosts ~/.ssh2/hostkeys; do
            [[ -d $i ]] && khd+=("$i"/*pub)
        done
    fi

    # If we have known_hosts files to use
    if ((${#kh[@]} + ${#khd[@]} > 0)); then
        if ((${#kh[@]} > 0)); then
            # https://man.openbsd.org/sshd.8#SSH_KNOWN_HOSTS_FILE_FORMAT
            for i in "${kh[@]}"; do
                while read -ra tmpkh; do
                    ((${#tmpkh[@]} == 0)) && continue
                    set -- "${tmpkh[@]}"
                    # Skip entries starting with | (hashed) and # (comment)
                    [[ $1 == [\|\#]* ]] && continue
                    # Ignore leading @foo (markers)
                    [[ $1 == @* ]] && shift
                    # Split entry on commas
                    local IFS=,
                    for host in $1; do
                        # Skip hosts containing wildcards
                        [[ $host == *[*?]* ]] && continue
                        # Remove leading [
                        host="${host#[}"
                        # Remove trailing ] + optional :port
                        host="${host%]?(:+([0-9]))}"
                        # Add host to candidates
                        COMPREPLY+=($host)
                    done
                    IFS=$ifs
                done <"$i"
            done
            COMPREPLY=($(compgen -W '${COMPREPLY[@]}' -- "$cur"))
        fi
        if ((${#khd[@]} > 0)); then
            # Needs to look for files called
            # .../.ssh2/key_22_<hostname>.pub
            # dont fork any processes, because in a cluster environment,
            # there can be hundreds of hostkeys
            for i in "${khd[@]}"; do
                if [[ $i == *key_22_$cur*.pub && -r $i ]]; then
                    host=${i/#*key_22_/}
                    host=${host/%.pub/}
                    COMPREPLY+=($host)
                fi
            done
        fi

        # apply suffix and prefix
        for i in ${!COMPREPLY[*]}; do
            COMPREPLY[i]=$prefix${COMPREPLY[i]}$suffix
        done
    fi

    # append any available aliases from ssh config files
    if [[ ${#config[@]} -gt 0 && -v aliases ]]; then
        local -a hosts=($(command sed -ne 's/^[[:blank:]]*[Hh][Oo][Ss][Tt][[:blank:]]\(.*\)$/\1/p' "${config[@]}"))
        if ((${#hosts[@]} != 0)); then
            COMPREPLY+=($(compgen -P "$prefix" \
                -S "$suffix" -W '${hosts[@]%%[*?%]*}' -X '\!*' -- "$cur"))
        fi
    fi

    # Add hosts reported by avahi-browse, if desired and it's available.
    if [[ ${COMP_KNOWN_HOSTS_WITH_AVAHI-} ]] &&
        type avahi-browse &>/dev/null; then
        # The original call to avahi-browse also had "-k", to avoid lookups
        # into avahi's services DB. We don't need the name of the service, and
        # if it contains ";", it may mistify the result. But on Gentoo (at
        # least), -k wasn't available (even if mentioned in the manpage) some
        # time ago, so...
        COMPREPLY+=($(compgen -P "$prefix" -S "$suffix" -W \
            "$(avahi-browse -cpr _workstation._tcp 2>/dev/null |
                awk -F';' '/^=/ { print $7 }' | sort -u)" -- "$cur"))
    fi

    # Add hosts reported by ruptime.
    if type ruptime &>/dev/null; then
        COMPREPLY+=($(compgen -W \
            "$(ruptime 2>/dev/null | awk '!/^ruptime:/ { print $1 }')" \
            -- "$cur"))
    fi

    # Add results of normal hostname completion, unless
    # `COMP_KNOWN_HOSTS_WITH_HOSTFILE' is set to an empty value.
    if [[ -n ${COMP_KNOWN_HOSTS_WITH_HOSTFILE-1} ]]; then
        COMPREPLY+=(
            $(compgen -A hostname -P "$prefix" -S "$suffix" -- "$cur"))
    fi

    $reset

    if [[ -v ipv4 ]]; then
        COMPREPLY=("${COMPREPLY[@]/*:*$suffix/}")
    fi
    if [[ -v ipv6 ]]; then
        COMPREPLY=("${COMPREPLY[@]/+([0-9]).+([0-9]).+([0-9]).+([0-9])$suffix/}")
    fi
    if [[ -v ipv4 || -v ipv6 ]]; then
        for i in "${!COMPREPLY[@]}"; do
            [[ ${COMPREPLY[i]} ]] || unset -v "COMPREPLY[i]"
        done
    fi

    __ltrim_colon_completions "$prefix$cur"

} # _known_hosts_real()
complete -F _known_hosts traceroute traceroute6 \
    fping fping6 telnet rsh rlogin ftp dig mtr ssh-installkeys showmount

# This meta-cd function observes the CDPATH variable, so that cd additionally
# completes on directories under those specified in CDPATH.
#
_cd()
{
    local cur prev words cword
    _init_completion || return

    local IFS=$'\n' i j k

    compopt -o filenames

    # Use standard dir completion if no CDPATH or parameter starts with /,
    # ./ or ../
    if [[ -z ${CDPATH:-} || $cur == ?(.)?(.)/* ]]; then
        _filedir -d
        return
    fi

    local -r mark_dirs=$(_rl_enabled mark-directories && echo y)
    local -r mark_symdirs=$(_rl_enabled mark-symlinked-directories && echo y)

    # we have a CDPATH, so loop on its contents
    for i in ${CDPATH//:/$'\n'}; do
        # create an array of matched subdirs
        k="${#COMPREPLY[@]}"
        for j in $(compgen -d -- $i/$cur); do
            if [[ ($mark_symdirs && -L $j || $mark_dirs && ! -L $j) && ! -d ${j#$i/} ]]; then
                j+="/"
            fi
            COMPREPLY[k++]=${j#$i/}
        done
    done

    _filedir -d

    if ((${#COMPREPLY[@]} == 1)); then
        i=${COMPREPLY[0]}
        if [[ $i == "$cur" && $i != "*/" ]]; then
            COMPREPLY[0]="${i}/"
        fi
    fi

    return
}
if shopt -q cdable_vars; then
    complete -v -F _cd -o nospace cd pushd
else
    complete -F _cd -o nospace cd pushd
fi

# A _command_offset wrapper function for use when the offset is unknown.
# Only intended to be used as a completion function directly associated
# with a command, not to be invoked from within other completion functions.
#
_command()
{
    local offset i

    # find actual offset, as position of the first non-option
    offset=1
    for ((i = 1; i <= COMP_CWORD; i++)); do
        if [[ ${COMP_WORDS[i]} != -* ]]; then
            offset=$i
            break
        fi
    done
    _command_offset $offset
}

# A meta-command completion function for commands like sudo(8), which need to
# first complete on a command, then complete according to that command's own
# completion definition.
#
_command_offset()
{
    # rewrite current completion context before invoking
    # actual command completion

    # find new first word position, then
    # rewrite COMP_LINE and adjust COMP_POINT
    local word_offset=$1 i j
    for ((i = 0; i < word_offset; i++)); do
        for ((j = 0; j <= ${#COMP_LINE}; j++)); do
            [[ $COMP_LINE == "${COMP_WORDS[i]}"* ]] && break
            COMP_LINE=${COMP_LINE:1}
            ((COMP_POINT--))
        done
        COMP_LINE=${COMP_LINE#"${COMP_WORDS[i]}"}
        ((COMP_POINT -= ${#COMP_WORDS[i]}))
    done

    # shift COMP_WORDS elements and adjust COMP_CWORD
    for ((i = 0; i <= COMP_CWORD - word_offset; i++)); do
        COMP_WORDS[i]=${COMP_WORDS[i + word_offset]}
    done
    for ((i; i <= COMP_CWORD; i++)); do
        unset 'COMP_WORDS[i]'
    done
    ((COMP_CWORD -= word_offset))

    COMPREPLY=()
    local cur
    _get_comp_words_by_ref cur

    if ((COMP_CWORD == 0)); then
        local IFS=$'\n'
        compopt -o filenames
        COMPREPLY=($(compgen -d -c -- "$cur"))
    else
        local cmd=${COMP_WORDS[0]} compcmd=${COMP_WORDS[0]}
        local cspec=$(complete -p $cmd 2>/dev/null)

        # If we have no completion for $cmd yet, see if we have for basename
        if [[ ! $cspec && $cmd == */* ]]; then
            cspec=$(complete -p ${cmd##*/} 2>/dev/null)
            [[ $cspec ]] && compcmd=${cmd##*/}
        fi
        # If still nothing, just load it for the basename
        if [[ ! $cspec ]]; then
            compcmd=${cmd##*/}
            _completion_loader $compcmd
            cspec=$(complete -p $compcmd 2>/dev/null)
        fi

        if [[ -n $cspec ]]; then
            if [[ ${cspec#* -F } != "$cspec" ]]; then
                # complete -F <function>

                # get function name
                local func=${cspec#*-F }
                func=${func%% *}

                if ((${#COMP_WORDS[@]} >= 2)); then
                    $func $cmd "${COMP_WORDS[-1]}" "${COMP_WORDS[-2]}"
                else
                    $func $cmd "${COMP_WORDS[-1]}"
                fi

                # restore initial compopts
                local opt
                while [[ $cspec == *" -o "* ]]; do
                    # FIXME: should we take "+o opt" into account?
                    cspec=${cspec#*-o }
                    opt=${cspec%% *}
                    compopt -o $opt
                    cspec=${cspec#$opt}
                done
            else
                cspec=${cspec#complete}
                cspec=${cspec%%$compcmd}
                COMPREPLY=($(eval compgen "$cspec" -- '$cur'))
            fi
        elif ((${#COMPREPLY[@]} == 0)); then
            # XXX will probably never happen as long as completion loader loads
            #     *something* for every command thrown at it ($cspec != empty)
            _minimal
        fi
    fi
}
complete -F _command aoss command "do" else eval exec ltrace nice nohup padsp \
    "then" time tsocks vsound xargs

_root_command()
{
    local PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin
    local root_command=$1
    _command
}
complete -F _root_command fakeroot gksu gksudo kdesudo really

# Return true if the completion should be treated as running as root
_complete_as_root()
{
    [[ $EUID -eq 0 || ${root_command:-} ]]
}

_longopt()
{
    local cur prev words cword split
    _init_completion -s || return

    case "${prev,,}" in
        --help | --usage | --version)
            return
            ;;
        --!(no-*)dir*)
            _filedir -d
            return
            ;;
        --!(no-*)@(file|path)*)
            _filedir
            return
            ;;
        --+([-a-z0-9_]))
            local argtype=$(LC_ALL=C $1 --help 2>&1 | command sed -ne \
                "s|.*$prev\[\{0,1\}=[<[]\{0,1\}\([-A-Za-z0-9_]\{1,\}\).*|\1|p")
            case ${argtype,,} in
                *dir*)
                    _filedir -d
                    return
                    ;;
                *file* | *path*)
                    _filedir
                    return
                    ;;
            esac
            ;;
    esac

    $split && return

    if [[ $cur == -* ]]; then
        COMPREPLY=($(compgen -W "$(LC_ALL=C $1 --help 2>&1 |
            while read -r line; do
                [[ $line =~ --[A-Za-z0-9]+([-_][A-Za-z0-9]+)*=? ]] &&
                    printf '%s\n' ${BASH_REMATCH[0]}
            done)" -- "$cur"))
        [[ ${COMPREPLY-} == *= ]] && compopt -o nospace
    elif [[ $1 == *@(rmdir|chroot) ]]; then
        _filedir -d
    else
        [[ $1 == *mkdir ]] && compopt -o nospace
        _filedir
    fi
}
# makeinfo and texi2dvi are defined elsewhere.
complete -F _longopt a2ps awk base64 bash bc bison cat chroot colordiff cp \
    csplit cut date df diff dir du enscript env expand fmt fold gperf \
    grep grub head irb ld ldd less ln ls m4 md5sum mkdir mkfifo mknod \
    mv netstat nl nm objcopy objdump od paste pr ptx readelf rm rmdir \
    sed seq sha{,1,224,256,384,512}sum shar sort split strip sum tac tail tee \
    texindex touch tr uname unexpand uniq units vdir wc who

declare -Ag _xspecs

_filedir_xspec()
{
    local cur prev words cword
    _init_completion || return

    _tilde "$cur" || return

    local IFS=$'\n' xspec=${_xspecs[${1##*/}]} tmp
    local -a toks

    toks=($(
        compgen -d -- "$(quote_readline "$cur")" | {
            while read -r tmp; do
                printf '%s\n' $tmp
            done
        }
    ))

    # Munge xspec to contain uppercase version too
    # https://lists.gnu.org/archive/html/bug-bash/2010-09/msg00036.html
    # news://news.gmane.io/4C940E1C.1010304@case.edu
    eval xspec="${xspec}"
    local matchop=!
    if [[ $xspec == !* ]]; then
        xspec=${xspec#!}
        matchop=@
    fi
    xspec="$matchop($xspec|${xspec^^})"

    toks+=($(
        eval compgen -f -X "'!$xspec'" -- '$(quote_readline "$cur")' | {
            while read -r tmp; do
                [[ -n $tmp ]] && printf '%s\n' $tmp
            done
        }
    ))

    # Try without filter if it failed to produce anything and configured to
    [[ -n ${COMP_FILEDIR_FALLBACK:-} && ${#toks[@]} -lt 1 ]] && {
        local reset=$(shopt -po noglob)
        set -o noglob
        toks+=($(compgen -f -- "$(quote_readline "$cur")"))
        IFS=' '
        $reset
        IFS=$'\n'
    }

    if ((${#toks[@]} != 0)); then
        compopt -o filenames
        COMPREPLY=("${toks[@]}")
    fi
}

_install_xspec()
{
    local xspec=$1 cmd
    shift
    for cmd in "$@"; do
        _xspecs[$cmd]=$xspec
    done
}
# bzcmp, bzdiff, bz*grep, bzless, bzmore intentionally not here, see Debian: #455510
_install_xspec '!*.?(t)bz?(2)' bunzip2 bzcat pbunzip2 pbzcat lbunzip2 lbzcat
_install_xspec '!*.@(zip|[aegjswx]ar|exe|pk3|wsz|zargo|xpi|s[tx][cdiw]|sx[gm]|o[dt][tspgfc]|od[bm]|oxt|epub|apk|aab|ipa|do[ct][xm]|p[op]t[mx]|xl[st][xm]|pyz|whl|[Ff][Cc][Ss]td)' unzip zipinfo
_install_xspec '*.Z' compress znew
# zcmp, zdiff, z*grep, zless, zmore intentionally not here, see Debian: #455510
_install_xspec '!*.@(Z|[gGd]z|t[ag]z)' gunzip zcat
_install_xspec '!*.@(Z|[gGdz]z|t[ag]z)' unpigz
_install_xspec '!*.Z' uncompress
# lzcmp, lzdiff intentionally not here, see Debian: #455510
_install_xspec '!*.@(tlz|lzma)' lzcat lzegrep lzfgrep lzgrep lzless lzmore unlzma
_install_xspec '!*.@(?(t)xz|tlz|lzma)' unxz xzcat
_install_xspec '!*.lrz' lrunzip
_install_xspec '!*.@(gif|jp?(e)g|miff|tif?(f)|pn[gm]|p[bgp]m|bmp|xpm|ico|xwd|tga|pcx)' ee
_install_xspec '!*.@(gif|jp?(e)g|tif?(f)|png|p[bgp]m|bmp|x[bp]m|rle|rgb|pcx|fits|pm|svg)' qiv
_install_xspec '!*.@(gif|jp?(e)g?(2)|j2[ck]|jp[2f]|tif?(f)|png|p[bgp]m|bmp|x[bp]m|rle|rgb|pcx|fits|pm|?(e)ps)' xv
_install_xspec '!*.@(@(?(e)ps|?(E)PS|pdf|PDF)?(.gz|.GZ|.bz2|.BZ2|.Z))' gv ggv kghostview
_install_xspec '!*.@(dvi|DVI)?(.@(gz|Z|bz2))' xdvi kdvi
_install_xspec '!*.dvi' dvips dviselect dvitype dvipdf advi dvipdfm dvipdfmx
_install_xspec '!*.[pf]df' acroread gpdf
_install_xspec '!*.@(pdf|fdf)?(.@(gz|GZ|bz2|BZ2|Z))' xpdf
_install_xspec '!*.@(?(e)ps|pdf)' kpdf
_install_xspec '!*.@(okular|@(?(e|x)ps|?(E|X)PS|[pf]df|[PF]DF|dvi|DVI|cb[rz]|CB[RZ]|djv?(u)|DJV?(U)|dvi|DVI|gif|jp?(e)g|miff|tif?(f)|pn[gm]|p[bgp]m|bmp|xpm|ico|xwd|tga|pcx|GIF|JP?(E)G|MIFF|TIF?(F)|PN[GM]|P[BGP]M|BMP|XPM|ICO|XWD|TGA|PCX|epub|EPUB|odt|ODT|fb?(2)|FB?(2)|mobi|MOBI|g3|G3|chm|CHM)?(.?(gz|GZ|bz2|BZ2|xz|XZ)))' okular
_install_xspec '!*.pdf' epdfview pdfunite
_install_xspec '!*.@(cb[rz7t]|djv?(u)|?(e)ps|pdf)' zathura
_install_xspec '!*.@(?(e)ps|pdf)' ps2pdf ps2pdf12 ps2pdf13 ps2pdf14 ps2pdfwr
_install_xspec '!*.texi*' makeinfo texi2html
_install_xspec '!*.@(?(la)tex|texi|dtx|ins|ltx|dbj)' tex latex slitex jadetex pdfjadetex pdftex pdflatex texi2dvi xetex xelatex luatex lualatex
_install_xspec '!*.mp3' mpg123 mpg321 madplay
_install_xspec '!*@(.@(mp?(e)g|MP?(E)G|wm[av]|WM[AV]|avi|AVI|asf|vob|VOB|bin|dat|divx|DIVX|vcd|ps|pes|fli|flv|FLV|fxm|FXM|viv|rm|ram|yuv|mov|MOV|qt|QT|web[am]|WEB[AM]|mp[234]|MP[234]|m?(p)4[av]|M?(P)4[AV]|mkv|MKV|og[agmvx]|OG[AGMVX]|t[ps]|T[PS]|m2t?(s)|M2T?(S)|mts|MTS|wav|WAV|flac|FLAC|asx|ASX|mng|MNG|srt|m[eo]d|M[EO]D|s[3t]m|S[3T]M|it|IT|xm|XM)|+([0-9]).@(vdr|VDR))?(.@(crdownload|part))' xine aaxine fbxine
_install_xspec '!*@(.@(mp?(e)g|MP?(E)G|wm[av]|WM[AV]|avi|AVI|asf|vob|VOB|bin|dat|divx|DIVX|vcd|ps|pes|fli|flv|FLV|fxm|FXM|viv|rm|ram|yuv|mov|MOV|qt|QT|web[am]|WEB[AM]|mp[234]|MP[234]|m?(p)4[av]|M?(P)4[AV]|mkv|MKV|og[agmvx]|OG[AGMVX]|t[ps]|T[PS]|m2t?(s)|M2T?(S)|mts|MTS|wav|WAV|flac|FLAC|asx|ASX|mng|MNG|srt|m[eo]d|M[EO]D|s[3t]m|S[3T]M|it|IT|xm|XM|iso|ISO)|+([0-9]).@(vdr|VDR))?(.@(crdownload|part))' kaffeine dragon totem
_install_xspec '!*.@(avi|asf|wmv)' aviplay
_install_xspec '!*.@(rm?(j)|ra?(m)|smi?(l))' realplay
_install_xspec '!*.@(mpg|mpeg|avi|mov|qt)' xanim
_install_xspec '!*.@(og[ag]|m3u|flac|spx)' ogg123
_install_xspec '!*.@(mp3|og[ag]|pls|m3u)' gqmpeg freeamp
_install_xspec '!*.fig' xfig
_install_xspec '!*.@(mid?(i)|cmf)' playmidi
_install_xspec '!*.@(mid?(i)|rmi|rcp|[gr]36|g18|mod|xm|it|x3m|s[3t]m|kar)' timidity
_install_xspec '!*.@(669|abc|am[fs]|d[bs]m|dmf|far|it|mdl|m[eo]d|mid?(i)|mt[2m]|oct|okt?(a)|p[st]m|s[3t]m|ult|umx|wav|xm)' modplugplay modplug123
_install_xspec '*.@([ao]|so|so.!(conf|*/*)|[rs]pm|gif|jp?(e)g|mp3|mp?(e)g|avi|asf|ogg|class)' vi vim gvim rvim view rview rgvim rgview gview emacs xemacs sxemacs kate kwrite
_install_xspec '!*.@(zip|z|gz|tgz)' bzme
# konqueror not here on purpose, it's more than a web/html browser
_install_xspec '!*.@(?([xX]|[sS])[hH][tT][mM]?([lL]))' netscape mozilla lynx galeon dillo elinks amaya epiphany
_install_xspec '!*.@(sxw|stw|sxg|sgl|doc?([mx])|dot?([mx])|rtf|txt|htm|html|?(f)odt|ott|odm|pdf)' oowriter lowriter
_install_xspec '!*.@(sxi|sti|pps?(x)|ppt?([mx])|pot?([mx])|?(f)odp|otp)' ooimpress loimpress
_install_xspec '!*.@(sxc|stc|xls?([bmx])|xlw|xlt?([mx])|[ct]sv|?(f)ods|ots)' oocalc localc
_install_xspec '!*.@(sxd|std|sda|sdd|?(f)odg|otg)' oodraw lodraw
_install_xspec '!*.@(sxm|smf|mml|odf)' oomath lomath
_install_xspec '!*.odb' oobase lobase
_install_xspec '!*.[rs]pm' rpm2cpio
_install_xspec '!*.aux' bibtex
_install_xspec '!*.po' poedit gtranslator kbabel lokalize
_install_xspec '!*.@([Pp][Rr][Gg]|[Cc][Ll][Pp])' harbour gharbour hbpp
_install_xspec '!*.[Hh][Rr][Bb]' hbrun
_install_xspec '!*.ly' lilypond ly2dvi
_install_xspec '!*.@(dif?(f)|?(d)patch)?(.@([gx]z|bz2|lzma))' cdiff
_install_xspec '!@(*.@(ks|jks|jceks|p12|pfx|bks|ubr|gkr|cer|crt|cert|p7b|pkipath|pem|p10|csr|crl)|cacerts)' portecle
_install_xspec '!*.@(mp[234c]|og[ag]|@(fl|a)ac|m4[abp]|spx|tta|w?(a)v|wma|aif?(f)|asf|ape)' kid3 kid3-qt
unset -f _install_xspec

# Minimal completion to use as fallback in _completion_loader.
_minimal()
{
    local cur prev words cword split
    _init_completion -s || return
    $split && return
    _filedir
}
# Complete the empty string to allow completion of '>', '>>', and '<' on < 4.3
# https://lists.gnu.org/archive/html/bug-bash/2012-01/msg00045.html
complete -F _minimal ''

__load_completion()
{
    local -a dirs=(${BASH_COMPLETION_USER_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion}/completions)
    local ifs=$IFS IFS=: dir cmd="${1##*/}" compfile
    [[ -n $cmd ]] || return 1
    for dir in ${XDG_DATA_DIRS:-/usr/local/share:/usr/share}; do
        dirs+=($dir/bash-completion/completions)
    done
    IFS=$ifs

    if [[ $BASH_SOURCE == */* ]]; then
        dirs+=("${BASH_SOURCE%/*}/completions")
    else
        dirs+=(./completions)
    fi

    local backslash=
    if [[ $cmd == \\* ]]; then
        cmd="${cmd:1}"
        # If we already have a completion for the "real" command, use it
        $(complete -p "$cmd" 2>/dev/null || echo false) "\\$cmd" && return 0
        backslash=\\
    fi

    for dir in "${dirs[@]}"; do
        [[ -d $dir ]] || continue
        for compfile in "$cmd" "$cmd.bash" "_$cmd"; do
            compfile="$dir/$compfile"
            # Avoid trying to source dirs; https://bugzilla.redhat.com/903540
            if [[ -f $compfile ]] && . "$compfile" &>/dev/null; then
                [[ $backslash ]] && $(complete -p "$cmd") "\\$cmd"
                return 0
            fi
        done
    done

    # Look up simple "xspec" completions
    [[ -v _xspecs[$cmd] ]] &&
        complete -F _filedir_xspec "$cmd" "$backslash$cmd" && return 0

    return 1
}

# set up dynamic completion loading
_completion_loader()
{
    # $1=_EmptycmD_ already for empty cmds in bash 4.3, set to it for earlier
    local cmd="${1:-_EmptycmD_}"

    __load_completion "$cmd" && return 124

    # Need to define *something*, otherwise there will be no completion at all.
    complete -F _minimal -- "$cmd" && return 124
} &&
    complete -D -F _completion_loader

# Function for loading and calling functions from dynamically loaded
# completion files that may not have been sourced yet.
# @param $1 completion file to load function from in case it is missing
# @param $2... function and its arguments
_xfunc()
{
    set -- "$@"
    local srcfile=$1
    shift
    declare -F $1 &>/dev/null || __load_completion "$srcfile"
    "$@"
}

# source compat completion directory definitions
compat_dir=${BASH_COMPLETION_COMPAT_DIR:-/etc/bash_completion.d}
if [[ -d $compat_dir && -r $compat_dir && -x $compat_dir ]]; then
    for i in "$compat_dir"/*; do
        [[ ${i##*/} != @($_backup_glob|Makefile*|$_blacklist_glob) && -f \
        $i && -r $i ]] && . "$i"
    done
fi
unset compat_dir i _blacklist_glob

# source user completion file
user_completion=${BASH_COMPLETION_USER_FILE:-~/.bash_completion}
[[ ${BASH_SOURCE[0]} != "$user_completion" && -r $user_completion && -f $user_completion ]] &&
    . $user_completion
unset user_completion

unset -f have
unset have

set $BASH_COMPLETION_ORIGINAL_V_VALUE
unset BASH_COMPLETION_ORIGINAL_V_VALUE

# ex: filetype=sh
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    /libc.conf d4d833fd095fb7b90e1bb4a547f16de6
Description: GNU C Library: Binaries
 This package contains utility programs related to the GNU C Library.
 .
  * getconf: query system configuration variables
  * getent: get entries from administrative databases
  * iconv, iconvconfig: convert between character encodings
  * ldd, ldconfig: print/configure shared library dependencies
  * locale, localedef: show/generate locale definitions
  * tzselect, zdump, zic: select/dump/compile time zones
Triggers-Pending: ldconfig
Homepage: https://www.gnu.org/software/libc/libc.html

Package: libc-l10n
Status: install ok installed
Priority: standard
Section: localization
Installed-Size: 4349
Maintainer: GNU Libc Maintainers <debian-glibc@lists.debian.org>
Architecture: all
Multi-Arch: foreign
Source: glibc
Version: 2.36-9+deb12u10
Description: GNU C Library: localization files
 This package contains the translation files for the GNU C library and
 utility programs.
Homepage: https://www.gnu.org/software/libc/libc.html

Package: libc6
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 12996
Maintainer: GNU Libc Maintainers <debian-glibc@lists.debian.org>
Architecture: amd64
Multi-Arch: same
Source: glibc
Version: 2.36-9+deb12u10
Replaces: libc6-amd64
Depends: libgcc-s1
Recommends: libidn2-0 (>= 2.0.5~)
Suggests: glibc-doc, debconf | debconf-2.0, libc-l10n, locales, libnss-nis, libnss-nisplus
Breaks: aide (<< 0.17.3-4+b3), busybox (<< 1.30.1-6), chrony (<< 4.2-3~), fakechroot (<< 2.19-3.5), firefox (<< 91~), firefox-esr (<< 91~), gnumach-image-1.8-486 (<< 2:1.8+git20210923~), gnumach-image-1.8-486-dbg (<< 2:1.8+git20210923~), gnumach-image-1.8-xen-486 (<< 2:1.8+git20210923~), gnumach-image-1.8-xen-486-dbg (<< 2:1.8+git20210923~), hurd (<< 1:0.9.git20220301-2), ioquake3 (<< 1.36+u20200211.f2c61c1~dfsg-2~), iraf-fitsutil (<< 2018.07.06-4), libgegl-0.4-0 (<< 0.4.18), libtirpc1 (<< 0.2.3), locales (<< 2.36), locales-all (<< 2.36), macs (<< 2.2.7.1-3~), nocache (<< 1.1-1~), nscd (<< 2.36), openarena (<< 0.8.8+dfsg-4~), openssh-server (<< 1:8.1p1-5), python3-iptables (<< 1.0.0-2), r-cran-later (<< 0.7.5+dfsg-2), tinydns (<< 1:1.05-14), valgrind (<< 1:3.19.0-1~), wcc (<< 0.0.2+dfsg-3)
Conffiles:
 /etc/ld.so.conf.d/x86_64-linux-gnu.conf d4e7a7b88a71b5ffd9e2644e71a0cfab
Description: GNU C Library: Shared libraries
 Contains the standard libraries that are used by nearly all programs on
 the system. This package includes shared versions of the standard C library
 and the standard math library, as well as many others.
Homepage: https://www.gnu.org/software/libc/libc.html

Package: libcap-ng0
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 65
Maintainer: Håvard F. Aasen <havard.f.aasen@pfft.no>
Architecture: amd64
Multi-Arch: same
Source: libcap-ng (0.8.3-1)
Version: 0.8.3-1+b3
Depends: libc6 (>= 2.33)
Description: alternate POSIX capabilities library
 This library implements the user-space interfaces to the POSIX
 1003.1e capabilities available in Linux kernels.  These capabilities are
 a partitioning of the all powerful root privilege into a set of distinct
 privileges.
 .
 The libcap-ng library is intended to make programming with POSIX
 capabilities much easier than the traditional libcap library.
 .
 This package contains dynamic libraries for libcap-ng.
Homepage: https://people.redhat.com/sgrubb/libcap-ng

Package: libcap2
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 94
Maintainer: Christian Kastner <ckk@debian.org>
Architecture: amd64
Multi-Arch: same
Version: 1:2.66-4+deb12u1
Depends: libc6 (>= 2.34)
Description: POSIX 1003.1e capabilities (library)
 Libcap implements the user-space interfaces to the POSIX 1003.1e capabilities
 available in Linux kernels. These capabilities are a partitioning of the all
 powerful root privilege into a set of distinct privileges.
 .
 This package contains the shared library.
Homepage: https://sites.google.com/site/fullycapable/

Package: libcap2-bin
Status: install ok installed
Priority: important
Section: utils
Installed-Size: 132
Maintainer: Christian Kastner <ckk@debian.org>
Architecture: amd64
Multi-Arch: foreign
Source: libcap2
Version: 1:2.66-4+deb12u1
Replaces: libcap-bin
Depends: libc6 (>= 2.34), libcap2 (>= 1:2.63)
Recommends: libpam-cap
Breaks: libcap-bin
Description: POSIX 1003.1e capabilities (utilities)
 Libcap implements the user-space interfaces to the POSIX 1003.1e capabilities
 available in Linux kernels. These capabilities are a partitioning of the all
 powerful root privilege into a set of distinct privileges.
 .
 This package contains additional utilities.
Homepage: https://sites.google.com/site/fullycapable/

Package: libcbor0.8
Status: install ok unpacked
Priority: optional
Section: libs
Installed-Size: 98
Maintainer: Vincent Bernat <bernat@debian.org>
Architecture: amd64
Multi-Arch: same
Source: libcbor (0.8.0-2)
Version: 0.8.0-2+b1
Depends: libc6 (>= 2.14)
Description: library for parsing and generating CBOR (RFC 7049)
 CBOR is a general-purpose schema-less binary data format, defined in
 RFC 7049. This package provides a C library for parsing and generating
 CBOR. The main features are:
 .
  - Complete RFC conformance
  - Robust C99 implementation
  - Layered architecture offers both control and convenience
  - Flexible memory management
  - No shared global state - threading friendly
  - Proper handling of UTF-8
  - Full support for streams & incremental processing
  - Extensive documentation and test suite
  - No runtime dependencies, small footprint
 .
 This package contains the runtime library.
Homepage: https://github.com/PJK/libcbor

Package: libcom-err2
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 54
Maintainer: Theodore Y. Ts'o <tytso@mit.edu>
Architecture: amd64
Multi-Arch: same
Source: e2fsprogs
Version: 1.47.0-2
Replaces: libcomerr2 (<< 1.43.9-1~)
Provides: libcomerr2 (= 1.47.0-2)
Depends: libc6 (>= 2.17)
Breaks: libcomerr2 (<< 1.43.9-1~)
Description: common error description library
 libcomerr is an attempt to present a common error-handling mechanism to
 manipulate the most common form of error code in a fashion that does not
 have the problems identified with mechanisms commonly in use.
Homepage: http://e2fsprogs.sourceforge.net

Package: libcrypt1
Protected: yes
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 233
Maintainer: Marco d'Itri <md@linux.it>
Architecture: amd64
Multi-Arch: same
Source: libxcrypt
Version: 1:4.4.33-2
Replaces: libc6 (<< 2.29-4)
Depends: libc6 (>= 2.36)
Conflicts: libpam0g (<< 1.4.0-10)
Description: libcrypt shared library
 libxcrypt is a modern library for one-way hashing of passwords.
 It supports DES, MD5, NTHASH, SUNMD5, SHA-2-256, SHA-2-512, and
 bcrypt-based password hashes
 It provides the traditional Unix 'crypt' and 'crypt_r' interfaces,
 as well as a set of extended interfaces like 'crypt_gensalt'.
Important: yes

Package: libcryptsetup12
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 563
Maintainer: Debian Cryptsetup Team <pkg-cryptsetup-devel@alioth-lists.debian.net>
Architecture: amd64
Multi-Arch: same
Source: cryptsetup
Version: 2:2.6.1-4~deb12u2
Depends: libargon2-1 (>= 0~20171227), libblkid1 (>= 2.24.2), libc6 (>= 2.34), libdevmapper1.02.1 (>= 2:1.02.97), libjson-c5 (>= 0.15), libssl3 (>= 3.0.0), libuuid1 (>= 2.16)
Description: disk encryption support - shared library
 Cryptsetup provides an interface for configuring encryption on block
 devices (such as /home or swap partitions), using the Linux kernel
 device mapper target dm-crypt. It features integrated Linux Unified Key
 Setup (LUKS) support.
 .
 This package provides the libcryptsetup shared library.
Homepage: https://gitlab.com/cryptsetup/cryptsetup

Package: libdb5.3
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 1833
Maintainer: Bastian Germann <bage@debian.org>
Architecture: amd64
Multi-Arch: same
Source: db5.3
Version: 5.3.28+dfsg2-1
Depends: libc6 (>= 2.34)
Description: Berkeley v5.3 Database Libraries [runtime]
 This is the runtime package for programs that use the v5.3 Berkeley
 database library.
Homepage: http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/overview/index.html

Package: libdbus-1-3
Status: install ok unpacked
Priority: optional
Section: libs
Installed-Size: 468
Maintainer: Utopia Maintenance Team <pkg-utopia-maintainers@lists.alioth.debian.org>
Architecture: amd64
Multi-Arch: same
Source: dbus
Version: 1.14.10-1~deb12u1
Depends: libc6 (>= 2.34), libsystemd0
Recommends: dbus
Description: simple interprocess messaging system (library)
 D-Bus is a message bus, used for sending messages between applications.
 Conceptually, it fits somewhere in between raw sockets and CORBA in
 terms of complexity.
 .
 D-Bus supports broadcast messages, asynchronous messages (thus
 decreasing latency), authentication, and more. It is designed to be
 low-overhead; messages are sent using a binary protocol, not using
 XML. D-Bus also supports a method call mapping for its messages, but
 it is not required; this makes using the system quite simple.
 .
 It comes with several bindings, including GLib, Python, Qt and Java.
 .
 The message bus daemon can be found in the dbus-daemon package.
Homepage: https://dbus.freedesktop.org/

Package: libdebconfclient0
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 37
Maintainer: Debian Install System Team <debian-boot@lists.debian.org>
Architecture: amd64
Multi-Arch: same
Source: cdebconf
Version: 0.270
Depends: libc6 (>= 2.4)
Description: Debian Configuration Management System (C-implementation library)
 Debconf is a configuration management system for Debian packages. It is
 used by some packages to prompt you for information before they are
 installed. cdebconf is a reimplementation of the original debconf in C.
 .
 This library allows C programs to interface with cdebconf.

Package: libdevmapper1.02.1
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 474
Maintainer: Debian LVM Team <team+lvm@tracker.debian.org>
Architecture: amd64
Multi-Arch: same
Source: lvm2 (2.03.16-2)
Version: 2:1.02.185-2
Depends: libc6 (>= 2.33), libselinux1 (>= 3.1~), libudev1 (>= 183), dmsetup (>= 2:1.02.185-2~)
Description: Linux Kernel Device Mapper userspace library
 The Linux Kernel Device Mapper is the LVM (Linux Logical Volume Management)
 Team's implementation of a minimalistic kernel-space driver that handles
 volume management, while keeping knowledge of the underlying device layout
 in user-space.  This makes it useful for not only LVM, but software raid,
 and other drivers that create "virtual" block devices.
 .
 This package contains the (user-space) shared library for accessing the
 device-mapper; it allows usage of the device-mapper through a clean,
 consistent interface (as opposed to through kernel ioctls).
Homepage: https://sourceware.org/lvm2/

Package: libdiscover2
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 263
Maintainer: Debian Install System Team <debian-boot@lists.debian.org>
Architecture: amd64
Source: discover
Version: 2.1.2-10
Depends: libc6 (>= 2.33), libexpat1 (>= 2.0.1), libusb-1.0-0 (>= 2:1.0.8), discover-data (>> 2.2004.04)
Conflicts: discover (<< 2.0), discover1 (<< 2.0), libdiscover1 (<< 2.0)
Conffiles:
 /etc/discover.conf.d/00discover 210206a7fc71cd0e5dae4836809e41e9
Description: hardware identification library
 libdiscover is a library enabling identification of various PCI,
 PCMCIA, and USB devices.

Package: libedit2
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 258
Maintainer: LLVM Packaging Team <pkg-llvm-team@lists.alioth.debian.org>
Architecture: amd64
Multi-Arch: same
Source: libedit
Version: 3.1-20221030-2
Replaces: libedit-dev (<< 3.1-20180525-2~)
Depends: libbsd0 (>= 0.1.3), libc6 (>= 2.33), libtinfo6 (>= 6)
Description: BSD editline and history libraries
 Command line editor library provides generic line editing,
 history, and tokenization functions.
 .
 It slightly resembles GNU readline.
Homepage: https://www.thrysoee.dk/editline/

Package: libelf1
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 1036
Maintainer: Debian Elfutils Maintainers <debian-gcc@lists.debian.org>
Architecture: amd64
Multi-Arch: same
Source: elfutils
Version: 0.188-2.1
Depends: libc6 (>= 2.34), zlib1g (>= 1:1.1.4)
Description: library to read and write ELF files
 The libelf1 package provides a shared library which allows reading and
 writing ELF files on a high level.  Third party programs depend on
 this package to read internals of ELF files.  The programs of the
 elfutils package use it also to generate new ELF files.
 .
 This library is part of elfutils.
Homepage: https://sourceware.org/elfutils/

Package: libexpat1
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 387
Maintainer: Laszlo Boszormenyi (GCS) <gcs@debian.org>
Architecture: amd64
Multi-Arch: same
Source: expat
Version: 2.5.0-1+deb12u1
Depends: libc6 (>= 2.36)
Description: XML parsing C library - runtime library
 This package contains the runtime, shared library of expat, the C
 library for parsing XML. Expat is a stream-oriented parser in
 which an application registers handlers for things the parser
 might find in the XML document (like start tags).
Homepage: https://libexpat.github.io/

Package: libext2fs2
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 534
Maintainer: Theodore Y. Ts'o <tytso@mit.edu>
Architecture: amd64
Multi-Arch: same
Source: e2fsprogs
Version: 1.47.0-2
Replaces: e2fslibs (<< 1.43.9-1~)
Provides: e2fslibs (= 1.47.0-2)
Depends: libc6 (>= 2.34)
Breaks: e2fslibs (<< 1.43.9-1~)
Description: ext2/ext3/ext4 file system libraries
 The ext2, ext3 and ext4 file systems are successors of the original ext
 ("extended") file system. They are the main file system types used for
 hard disks on Debian and other Linux systems.
 .
 This package provides the ext2fs and e2p libraries, for userspace software
 that directly accesses extended file systems. Programs that use libext2fs
 include e2fsck, mke2fs, and tune2fs. Programs that use libe2p include
 dumpe2fs, chattr, and lsattr.
Homepage: http://e2fsprogs.sourceforge.net

Package: libfdisk1
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 533
Maintainer: util-linux packagers <util-linux@packages.debian.org>
Architecture: amd64
Multi-Arch: same
Source: util-linux
Version: 2.38.1-5+deb12u3
Depends: libblkid1 (>= 2.24.2), libc6 (>= 2.33), libuuid1 (>= 2.16)
Description: fdisk partitioning library
 The libfdisk library is used for manipulating partition tables. It is
 the core of the fdisk, cfdisk, and sfdisk tools.
Homepage: https://www.kernel.org/pub/linux/utils/util-linux/

Package: libffi8
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 68
Maintainer: Debian GCC Maintainers <debian-gcc@lists.debian.org>
Architecture: amd64
Multi-Arch: same
Source: libffi
Version: 3.4.4-1
Replaces: libffi8ubuntu1 (<< 3.4.2-1)
Provides: libffi8ubuntu1 (= 3.4.4-1)
Depends: libc6 (>= 2.34)
Breaks: libffi8ubuntu1 (<< 3.4.2-1)
Description: Foreign Function Interface library runtime
 A foreign function interface is the popular name for the interface that
 allows code written in one language to call code written in another
 language.
Homepage: https://sourceware.org/libffi/

Package: libfido2-1
Status: install ok unpacked
Priority: optional
Section: libs
Installed-Size: 241
Maintainer: Debian Authentication Maintainers <pkg-auth-maintainers@lists.alioth.debian.org>
Architecture: amd64
Multi-Arch: same
Source: libfido2 (1.12.0-2)
Version: 1.12.0-2+b1
Depends: libc6 (>= 2.36), libcbor0.8 (>= 0.8.0), libssl3 (>= 3.0.0), libudev1 (>= 183), zlib1g (>= 1:1.1.4)
Description: library for generating and verifying FIDO 2.0 objects
 A library for communicating with a FIDO device over USB or NFC, and for
 verifying attestation and assertion signatures. FIDO U2F (CTAP 1) and FIDO
 2.0 (CTAP 2) are supported.
 .
 This package contains the library.
Homepage: https://developers.yubico.com/libfido2/

Package: libgcc-s1
Protected: yes
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 140
Maintainer: Debian GCC Maintainers <debian-gcc@lists.debian.org>
Architecture: amd64
Multi-Arch: same
Source: gcc-12
Version: 12.2.0-14+deb12u1
Replaces: libgcc1 (<< 1:10)
Provides: libgcc1 (= 1:12.2.0-14+deb12u1)
Depends: gcc-12-base (= 12.2.0-14+deb12u1), libc6 (>= 2.35)
Description: GCC support library
 Shared version of the support library, a library of internal subroutines
 that GCC uses to overcome shortcomings of particular machines, or
 special needs for some languages.
Homepage: http://gcc.gnu.org/
Important: yes

Package: libgcrypt20
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 1592
Maintainer: Debian GnuTLS Maintainers <pkg-gnutls-maint@lists.alioth.debian.org>
Architecture: amd64
Multi-Arch: same
Version: 1.10.1-3
Depends: libc6 (>= 2.34), libgpg-error0 (>= 1.27)
Suggests: rng-tools
Description: LGPL Crypto library - runtime library
 libgcrypt contains cryptographic functions.  Many important free
 ciphers, hash algorithms and public key signing algorithms have been
 implemented:
 .
 Arcfour, Blowfish, CAST5, DES, AES, Twofish, Serpent, rfc2268 (rc2), SEED,
 Poly1305, Camellia, ChaCha20, IDEA, Salsa, SM4, Blake-2, CRC, MD2, MD4, MD5,
 RIPE-MD160, SM3, SHA-1, SHA-256, SHA-512, SHA3-224, SHA3-256, SHA3-384,
 SHA3-512, SHAKE128, SHAKE256, Tiger, Whirlpool, DSA, DSA2, ElGamal, RSA, ECC
 (Curve25519, sec256k1, GOST R 34.10-2001 and GOST R 34.10-2012, etc.)
Homepage: https://directory.fsf.org/project/libgcrypt/

Package: libgdbm-compat4
Status: install ok unpacked
Priority: optional
Section: libs
Installed-Size: 70
Maintainer: Nicolas Mora <babelouest@debian.org>
Architecture: amd64
Multi-Arch: same
Source: gdbm
Version: 1.23-3
Depends: libc6 (>= 2.33), libgdbm6 (>= 1.16)
Description: GNU dbm database routines (legacy support runtime version) 
 GNU dbm ('gdbm') is a library of database functions that use extendible
 hashing and works similarly to the standard UNIX 'dbm' functions.
 .
 The basic use of 'gdbm' is to store key/data pairs in a data file, thus
 providing a persistent version of the 'dictionary' Abstract Data Type
 ('hash' to perl programmers).
 This package includes library files, required to run old programs,
 that use legacy 'dbm' interface. For new programs, please use modern
 interface, provided by libgdbm6 and libgdbm-dev.
Homepage: https://gnu.org/software/gdbm

Package: libgdbm6
Status: install ok unpacked
Priority: optional
Section: libs
Installed-Size: 129
Maintainer: Nicolas Mora <babelouest@debian.org>
Architecture: amd64
Multi-Arch: same
Source: gdbm
Version: 1.23-3
Depends: libc6 (>= 2.34)
Suggests: gdbm-l10n (= 1.23-3)
Description: GNU dbm database routines (runtime version) 
 GNU dbm ('gdbm') is a library of database functions that use extendible
 hashing and works similarly to the standard UNIX 'dbm' functions.
 .
 The basic use of 'gdbm' is to store key/data pairs in a data file, thus
 providing a persistent version of the 'dictionary' Abstract Data Type
 ('hash' to perl programmers).
Homepage: https://gnu.org/software/gdbm

Package: libgmp10
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 855
Maintainer: Debian Science Team <debian-science-maintainers@lists.alioth.debian.org>
Architecture: amd64
Multi-Arch: same
Source: gmp
Version: 2:6.2.1+dfsg1-1.1
Depends: libc6 (>= 2.14)
Breaks: libmath-gmp-perl (<< 2.20-1), libmath-prime-util-gmp-perl (<< 0.51-2), postgresql-pgmp (<< 1.0.3-1)
Description: Multiprecision arithmetic library
 GNU MP is a programmer's library for arbitrary precision
 arithmetic (ie, a bignum package).  It can operate on signed
 integer, rational, and floating point numeric types.
 .
 It has a rich set of functions, and the functions have a regular
 interface.
Homepage: https://gmplib.org/

Package: libgnutls30
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 3382
Maintainer: Debian GnuTLS Maintainers <pkg-gnutls-maint@lists.alioth.debian.org>
Architecture: amd64
Multi-Arch: same
Source: gnutls28
Version: 3.7.9-2+deb12u5
Depends: libc6 (>= 2.34), libgmp10 (>= 2:6.2.1+dfsg1), libhogweed6 (>= 3.6), libidn2-0 (>= 2.0.0), libnettle8 (>= 3.7~), libp11-kit0 (>= 0.23.18.1), libtasn1-6 (>= 4.14), libunistring2 (>= 0.9.7)
Suggests: gnutls-bin
Description: GNU TLS library - main runtime library
 GnuTLS is a portable library which implements the Transport Layer
 Security (TLS 1.0, 1.1, 1.2, 1.3) and Datagram
 Transport Layer Security (DTLS 1.0, 1.2) protocols.
 .
 GnuTLS features support for:
  - certificate path validation, as well as DANE and trust on first use.
  - the Online Certificate Status Protocol (OCSP).
  - public key methods, including RSA and Elliptic curves, as well as password
    and key authentication methods such as SRP and PSK protocols.
  - all the strong encryption algorithms, including AES and Camellia.
  - CPU-assisted cryptography with VIA padlock and AES-NI instruction sets.
  - HSMs and cryptographic tokens, via PKCS #11.
 .
 This package contains the main runtime library.
Homepage: https://www.gnutls.org/

Package: libgpg-error0
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 192
Maintainer: Debian GnuPG Maintainers <pkg-gnupg-maint@lists.alioth.debian.org>
Architecture: amd64
Multi-Arch: same
Source: libgpg-error
Version: 1.46-1
Depends: libc6 (>= 2.34)
Recommends: libgpg-error-l10n
Description: GnuPG development runtime library
 Library that defines common error values, messages, and common
 runtime functionality for all GnuPG components.  Among these are GPG,
 GPGSM, GPGME, GPG-Agent, libgcrypt, pinentry, SmartCard Daemon and
 possibly more in the future.
 .
 It will likely be renamed "gpgrt" in the future.
Homepage: https://www.gnupg.org/related_software/libgpg-error/

Package: libgssapi-krb5-2
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 425
Maintainer: Sam Hartman <hartmans@debian.org>
Architecture: amd64
Multi-Arch: same
Source: krb5
Version: 1.20.1-2+deb12u3
Depends: libc6 (>= 2.33), libcom-err2 (>= 1.43.9), libk5crypto3 (>= 1.20), libkrb5-3 (= 1.20.1-2+deb12u3), libkrb5support0 (>= 1.15~beta1)
Suggests: krb5-doc, krb5-user
Breaks: moonshot-gss-eap (<= 1.0)
Description: MIT Kerberos runtime libraries - krb5 GSS-API Mechanism
 Kerberos is a system for authenticating users and services on a network.
 Kerberos is a trusted third-party service.  That means that there is a
 third party (the Kerberos server) that is trusted by all the entities on
 the network (users and services, usually called "principals").
 .
 This is the MIT reference implementation of Kerberos V5.
 .
 This package contains the runtime library for the MIT Kerberos
 implementation of GSS-API used by applications and Kerberos clients.
Homepage: https://web.mit.edu/kerberos/

Package: libhogweed6
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 463
Maintainer: Magnus Holmgren <holmgren@debian.org>
Architecture: amd64
Multi-Arch: same
Source: nettle
Version: 3.8.1-2
Depends: libc6 (>= 2.14), libgmp10 (>= 2:6.2.1+dfsg1), libnettle8
Description: low level cryptographic library (public-key cryptos)
 Nettle is a cryptographic library that is designed to fit easily in more or
 less any context: In crypto toolkits for object-oriented languages (C++,
 Python, Pike, ...), in applications like LSH or GNUPG, or even in kernel
 space.
 .
 It tries to solve a problem of providing a common set of cryptographic
 algorithms for higher-level applications by implementing a
 context-independent set of cryptographic algorithms. In that light, Nettle
 doesn't do any memory allocation or I/O, it simply provides the
 cryptographic algorithms for the application to use in any environment and
 in any way it needs.
 .
 This package contains the asymmetric cryptographic algorithms, which,
 require the GNU multiple precision arithmetic library (libgmp) for
 their large integer computations.
Homepage: http://www.lysator.liu.se/~nisse/nettle/

Package: libidn2-0
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 439
Maintainer: Debian Libidn team <help-libidn@gnu.org>
Architecture: amd64
Multi-Arch: same
Source: libidn2 (2.3.3-1)
Version: 2.3.3-1+b1
Depends: libc6 (>= 2.14), libunistring2 (>= 0.9.7)
Description: Internationalized domain names (IDNA2008/TR46) library
 Libidn2 implements the revised algorithm for internationalized domain
 names called IDNA2008/TR46.
 .
 This package contains runtime libraries.
Homepage: https://www.gnu.org/software/libidn/#libidn2

Package: libip4tc2
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 66
Maintainer: Debian Netfilter Packaging Team <pkg-netfilter-team@lists.alioth.debian.org>
Architecture: amd64
Multi-Arch: same
Source: iptables
Version: 1.8.9-2
Depends: libc6 (>= 2.28)
Description: netfilter libip4tc library
 The iptables/xtables framework has been replaced by nftables. You should
 consider migrating now.
 .
 This package contains the user-space iptables (IPv4) C library from the
 Netfilter xtables framework.
 .
 iptables IPv4 ruleset ADT and kernel interface.
 .
 This library has been considered private for years (and still is), in the
 sense of changing symbols and backward compatibility not guaranteed.
Homepage: https://www.netfilter.org/

Package: libjansson4
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 101
Maintainer: Alessandro Ghedini <ghedo@debian.org>
Architecture: amd64
Multi-Arch: same
Source: jansson
Version: 2.14-2
Depends: libc6 (>= 2.14)
Description: C library for encoding, decoding and manipulating JSON data
 Jansson is a C library for encoding, decoding and manipulating JSON data.
 .
 It features:
  * Simple and intuitive API and data model
  * Comprehensive documentation
  * No dependencies on other libraries
  * Full Unicode support (UTF-8)
  * Extensive test suite
Homepage: http://www.digip.org/jansson/

Package: libjson-c5
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 109
Maintainer: Nicolas Mora <babelouest@debian.org>
Architecture: amd64
Multi-Arch: same
Source: json-c
Version: 0.16-2
Depends: libc6 (>= 2.33)
Description: JSON manipulation library - shared library
 This library allows you to easily construct JSON objects in C,
 output them as JSON formatted strings and parse JSON formatted
 strings back into the C representation of JSON objects.
Homepage: https://github.com/json-c/json-c/wiki

Package: libk5crypto3
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 261
Maintainer: Sam Hartman <hartmans@debian.org>
Architecture: amd64
Multi-Arch: same
Source: krb5
Version: 1.20.1-2+deb12u3
Depends: libc6 (>= 2.33), libkrb5support0 (>= 1.20)
Suggests: krb5-doc, krb5-user
Breaks: libgssapi-krb5-2 (<= 1.18~), libkrb5-3 (<= 1.18~)
Description: MIT Kerberos runtime libraries - Crypto Library
 Kerberos is a system for authenticating users and services on a network.
 Kerberos is a trusted third-party service.  That means that there is a
 third party (the Kerberos server) that is trusted by all the entities on
 the network (users and services, usually called "principals").
 .
 This is the MIT reference implementation of Kerberos V5.
 .
 This package contains the runtime cryptography libraries used by
 applications and Kerberos clients.
Homepage: https://web.mit.edu/kerberos/

Package: libkeyutils1
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 40
Maintainer: Christian Kastner <ckk@debian.org>
Architecture: amd64
Multi-Arch: same
Source: keyutils
Version: 1.6.3-2
Depends: libc6 (>= 2.14)
Description: Linux Key Management Utilities (library)
 Keyutils is a set of utilities for managing the key retention facility in the
 kernel, which can be used by filesystems, block devices and more to gain and
 retain the authorization and encryption keys required to perform secure
 operations.
 .
 This package provides a wrapper library for the key management facility system
 calls.
Homepage: https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/keyutils.git

Package: libklibc
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 97
Maintainer: Debian Kernel Team <debian-kernel@lists.debian.org>
Architecture: amd64
Multi-Arch: same
Source: klibc
Version: 2.0.12-1
Description: minimal libc subset for use with initramfs
 klibc is intended to be a minimalistic libc subset for use with
 initramfs.  It is deliberately written for small size, minimal
 entanglement, and portability, not speed.  It is definitely a work in
 progress, and a lot of things are still missing.
Homepage: https://git.kernel.org/cgit/libs/klibc/klibc.git

Package: libkmod2
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 141
Maintainer: Marco d'Itri <md@linux.it>
Architecture: amd64
Multi-Arch: same
Source: kmod
Version: 30+20221128-1
Depends: libc6 (>= 2.33), liblzma5 (>= 5.1.1alpha+20120614), libssl3 (>= 3.0.0), libzstd1 (>= 1.5.2)
Description: libkmod shared library
 This library provides an API for insertion, removal, configuration and
 listing of kernel modules.

Package: libkrb5-3
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 1077
Maintainer: Sam Hartman <hartmans@debian.org>
Architecture: amd64
Multi-Arch: same
Source: krb5
Version: 1.20.1-2+deb12u3
Depends: libc6 (>= 2.34), libcom-err2 (>= 1.43.9), libk5crypto3 (>= 1.20), libkeyutils1 (>= 1.5.9), libkrb5support0 (= 1.20.1-2+deb12u3), libssl3 (>= 3.0.0)
Recommends: krb5-locales
Suggests: krb5-doc, krb5-user
Breaks: libapache2-mod-auth-kerb (<= 5.4-2.4), libsmbclient (<= 2:3.6.1-2), sssd (<= 1.2.1-4.3)
Description: MIT Kerberos runtime libraries
 Kerberos is a system for authenticating users and services on a network.
 Kerberos is a trusted third-party service.  That means that there is a
 third party (the Kerberos server) that is trusted by all the entities on
 the network (users and services, usually called "principals").
 .
 This is the MIT reference implementation of Kerberos V5.
 .
 This package contains the runtime library for the main Kerberos v5 API
 used by applications and Kerberos clients.
Homepage: https://web.mit.edu/kerberos/

Package: libkrb5support0
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 134
Maintainer: Sam Hartman <hartmans@debian.org>
Architecture: amd64
Multi-Arch: same
Source: krb5
Version: 1.20.1-2+deb12u3
Depends: libc6 (>= 2.34)
Breaks: libgssapi-krb5-2 (<< 1.20), libk5crypto3 (<< 1.20), libkadm5clnt-mit9 (<< 1.13~alpha1-1), libkadm5srv-mit9 (<< 1.13~alpha1-1), libkdb5-8 (<< 1.16)
Description: MIT Kerberos runtime libraries - Support library
 Kerberos is a system for authenticating users and services on a network.
 Kerberos is a trusted third-party service.  That means that there is a
 third party (the Kerberos server) that is trusted by all the entities on
 the network (users and services, usually called "principals").
 .
 This is the MIT reference implementation of Kerberos V5.
 .
 This package contains an internal runtime support library used by other
 Kerberos libraries.
Homepage: https://web.mit.edu/kerberos/

Package: liblocale-gettext-perl
Status: install ok installed
Priority: required
Section: perl
Installed-Size: 51
Maintainer: Debian Perl Group <pkg-perl-maintainers@lists.alioth.debian.org>
Architecture: amd64
Version: 1.07-5
Depends: libc6 (>= 2.3)
Pre-Depends: perl-base (>= 5.36.0-5), perlapi-5.36.0
Description: module using libc functions for internationalization in Perl
 The Locale::gettext module permits access from perl to the gettext() family of
 functions for retrieving message strings from databases constructed
 to internationalize software.
 .
 It provides gettext(), dgettext(), dcgettext(), textdomain(),
 bindtextdomain(), bind_textdomain_codeset(), ngettext(), dcngettext()
 and dngettext().
Homepage: https://metacpan.org/release/gettext

Package: liblz4-1
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 169
Maintainer: Nobuhiro Iwamatsu <iwamatsu@debian.org>
Architecture: amd64
Multi-Arch: same
Source: lz4
Version: 1.9.4-1
Replaces: liblz4-1a
Depends: libc6 (>= 2.14)
Breaks: liblz4-1a
Description: Fast LZ compression algorithm library - runtime
 LZ4 is a very fast lossless compression algorithm, providing compression speed
 at 400 MB/s per core, scalable with multi-cores CPU. It also features an
 extremely fast decoder, with speed in multiple GB/s per core, typically
 reaching RAM speed limits on multi-core systems.
 .
 This package includes the shared library.
Homepage: https://github.com/lz4/lz4

Package: liblzma5
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 333
Maintainer: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Architecture: amd64
Multi-Arch: same
Source: xz-utils
Version: 5.4.1-1
Depends: libc6 (>= 2.34)
Breaks: liblzma2 (<< 5.1.1alpha+20110809-3~)
Description: XZ-format compression library
 XZ is the successor to the Lempel-Ziv/Markov-chain Algorithm
 compression format, which provides memory-hungry but powerful
 compression (often better than bzip2) and fast, easy decompression.
 .
 The native format of liblzma is XZ; it also supports raw (headerless)
 streams and the older LZMA format used by lzma. (For 7-Zip's related
 format, use the p7zip package instead.)
Homepage: https://tukaani.org/xz/

Package: libmd0
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 79
Maintainer: Guillem Jover <guillem@debian.org>
Architecture: amd64
Multi-Arch: same
Source: libmd
Version: 1.0.4-2
Depends: libc6 (>= 2.33)
Description: message digest functions from BSD systems - shared library
 The libmd library provides various message digest ("hash") functions,
 as found on various BSDs on a library with the same name and with a
 compatible API.
Homepage: https://www.hadrons.org/software/libmd/

Package: libmnl0
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 46
Maintainer: Debian Netfilter Packaging Team <pkg-netfilter-team@lists.alioth.debian.org>
Architecture: amd64
Multi-Arch: same
Source: libmnl
Version: 1.0.4-3
Depends: libc6 (>= 2.14)
Description: minimalistic Netlink communication library
 libmnl is a minimalistic user-space library oriented to Netlink developers.
 There are a lot of common tasks in parsing, validating, constructing of
 both the Netlink header and TLVs that are repetitive and easy to get wrong.
 This library aims to provide simple helpers that allows you to re-use code
 and to avoid re-inventing the wheel.
 .
 The main features of this library are:
 .
 Small: the shared library requires around 30KB for an x86-based computer.
 .
 Simple: this library avoids complexity and elaborated abstractions that
 tend to hide Netlink details.
 .
 Easy to use: the library simplifies the work for Netlink-wise developers.
 It provides functions to make socket handling, message building,
 validating, parsing and sequence tracking, easier.
 .
 Easy to re-use: you can use the library to build your own abstraction
 layer on top of this library.
 .
 Decoupling: the interdependency of the main bricks that compose the
 library is reduced, i.e. the library provides many helpers, but the
 programmer is not forced to use them.
 .
 This package contains the shared libraries needed to run programs that use
 the minimalistic Netlink communication library.
Homepage: https://netfilter.org/projects/libmnl/

Package: libmount1
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 454
Maintainer: util-linux packagers <util-linux@packages.debian.org>
Architecture: amd64
Multi-Arch: same
Source: util-linux
Version: 2.38.1-5+deb12u3
Depends: libblkid1 (>= 2.17.2), libc6 (>= 2.34), libselinux1 (>= 3.1~)
Suggests: cryptsetup-bin
Description: device mounting library
 This device mounting library is used by mount and umount helpers.
Homepage: https://www.kernel.org/pub/linux/utils/util-linux/

Package: libncursesw6
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 412
Maintainer: Craig Small <csmall@debian.org>
Architecture: amd64
Multi-Arch: same
Source: ncurses
Version: 6.4-4
Depends: libtinfo6 (= 6.4-4), libc6 (>= 2.34)
Recommends: libgpm2
Description: shared libraries for terminal handling (wide character support)
 The ncurses library routines are a terminal-independent method of
 updating character screens with reasonable optimization.
 .
 This package contains the shared libraries necessary to run programs
 compiled with ncursesw, which includes support for wide characters.
Homepage: https://invisible-island.net/ncurses/

Package: libnettle8
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 520
Maintainer: Magnus Holmgren <holmgren@debian.org>
Architecture: amd64
Multi-Arch: same
Source: nettle
Version: 3.8.1-2
Depends: libc6 (>= 2.17)
Description: low level cryptographic library (symmetric and one-way cryptos)
 Nettle is a cryptographic library that is designed to fit easily in more or
 less any context: In crypto toolkits for object-oriented languages (C++,
 Python, Pike, ...), in applications like LSH or GNUPG, or even in kernel
 space.
 .
 It tries to solve a problem of providing a common set of cryptographic
 algorithms for higher-level applications by implementing a
 context-independent set of cryptographic algorithms. In that light, Nettle
 doesn't do any memory allocation or I/O, it simply provides the
 cryptographic algorithms for the application to use in any environment and
 in any way it needs.
 .
 This package contains the symmetric and one-way cryptographic
 algorithms. To avoid having this package depend on libgmp, the
 asymmetric cryptos reside in a separate library, libhogweed.
Homepage: http://www.lysator.liu.se/~nisse/nettle/

Package: libnewt0.52
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 365
Maintainer: Alastair McKinstry <mckinstry@debian.org>
Architecture: amd64
Multi-Arch: same
Source: newt (0.52.23-1)
Version: 0.52.23-1+b1
Depends: libc6 (>= 2.34), libslang2 (>= 2.2.4)
Recommends: libfribidi0
Description: Not Erik's Windowing Toolkit - text mode windowing with slang
 Newt is a windowing toolkit for text mode built from the slang library.
 It allows color text mode applications to easily use stackable windows,
 push buttons, check boxes, radio buttons, lists, entry fields, labels,
 and displayable text. Scrollbars are supported, and forms may be nested
 to provide extra functionality. This package contains the shared library
 for programs that have been built with newt.
Homepage: https://pagure.io/newt

Package: libnftables1
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 920
Maintainer: Debian Netfilter Packaging Team <pkg-netfilter-team@lists.alioth.debian.org>
Architecture: amd64
Multi-Arch: same
Source: nftables
Version: 1.0.6-2+deb12u2
Depends: libc6 (>= 2.34), libgmp10 (>= 2:6.2.1+dfsg1), libjansson4 (>= 2.14), libmnl0 (>= 1.0.3-4~), libnftnl11 (>= 1.2.2), libxtables12 (>= 1.6.0+snapshot20161117)
Description: Netfilter nftables high level userspace API library
 This library provides high level semantics to interact with the nftables
 framework by Netfilter project.
 .
 nftables replaces the old popular iptables, ip6tables, arptables and ebtables.
 .
 Netfilter software and nftables in particular are used in applications such
 as Internet connection sharing, firewalls, IP accounting, transparent
 proxying, advanced routing and traffic control.
 .
 A Linux kernel >= 3.13 is required. However, >= 4.14 is recommended.
 .
 This package contains the libnftables library.
Homepage: https://www.netfilter.org/

Package: libnftnl11
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 233
Maintainer: Debian Netfilter Packaging Team <pkg-netfilter-team@lists.alioth.debian.org>
Architecture: amd64
Multi-Arch: same
Source: libnftnl
Version: 1.2.4-2
Depends: libc6 (>= 2.34), libmnl0 (>= 1.0.3-4~)
Description: Netfilter nftables userspace API library
 libnftnl is the low-level library for Netfilter 4th generation
 framework nftables.
 .
 Is the user-space library for low-level interaction with
 nftables Netlink's API over libmnl.
Homepage: https://git.netfilter.org/libnftnl

Package: libnsl2
Status: install ok unpacked
Priority: optional
Section: libs
Installed-Size: 127
Maintainer: GNU Libc Maintainers <debian-glibc@lists.debian.org>
Architecture: amd64
Multi-Arch: same
Source: libnsl
Version: 1.3.0-2
Depends: libc6 (>= 2.14), libtirpc3 (>= 1.0.2)
Description: Public client interface for NIS(YP) and NIS+
 This package contains the libnsl library, which contains the public client
 interface for NIS(YP) and NIS+. This code was formerly part of glibc, but is
 now standalone to be able to link against TI-RPC for IPv6 support.
Homepage: https://github.com/thkukuk/libnsl

Package: libp11-kit0
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 1408
Maintainer: Debian GnuTLS Maintainers <pkg-gnutls-maint@lists.alioth.debian.org>
Architecture: amd64
Multi-Arch: same
Source: p11-kit
Version: 0.24.1-2
Depends: libc6 (>= 2.34), libffi8 (>= 3.4)
Description: library for loading and coordinating access to PKCS#11 modules - runtime
 The p11-kit library provides a way to load and enumerate Public-Key
 Cryptography Standard #11 modules, along with a standard configuration
 setup for installing PKCS#11 modules so that they're discoverable. It
 also solves problems with coordinating the use of PKCS#11 by different
 components or libraries living in the same process.
 .
 This package contains the shared library required for applications loading
 and accessing PKCS#11 modules.
Homepage: https://p11-glue.github.io/p11-glue/p11-kit.html

Package: libpam-modules
Status: install ok installed
Priority: required
Section: admin
Installed-Size: 1031
Maintainer: Sam Hartman <hartmans@debian.org>
Architecture: amd64
Multi-Arch: same
Source: pam
Version: 1.5.2-6+deb12u1
Replaces: libpam-umask, libpam0g-util
Provides: libpam-mkhomedir, libpam-motd, libpam-umask
Pre-Depends: libaudit1 (>= 1:2.2.1), libc6 (>= 2.34), libcrypt1 (>= 1:4.3.0), libdb5.3, libpam0g (>= 1.4.1), libselinux1 (>= 3.1~), debconf (>= 0.5) | debconf-2.0, libpam-modules-bin (= 1.5.2-6+deb12u1)
Conflicts: libpam-mkhomedir, libpam-motd, libpam-umask
Conffiles:
 /etc/security/access.conf dc21d0fd769d655b311d785670e5c6ae
 /etc/security/faillock.conf 164da8ffb87f3074179bc60b71d0b99f
 /etc/security/group.conf f1e26e8db6f7abd2d697d7dad3422c36
 /etc/security/limits.conf 0b1967ff9042a716ce6b01cb999aa1f5
 /etc/security/namespace.conf 6b3796403421d66db7defc46517711bc
 /etc/security/namespace.init d9e6a7c85e966427ef23a04ec6c7000f
 /etc/security/pam_env.conf 89cc8702173d5cd51abc152ae9f8d6bc
 /etc/security/sepermit.conf 3d82df292d497bbeaaf8ebef18cd14f1
 /etc/security/time.conf 06e05c6079e839c8833ac7c3abfde192
Description: Pluggable Authentication Modules for PAM
 This package completes the set of modules for PAM. It includes the
  pam_unix.so module as well as some specialty modules.
Homepage: http://www.linux-pam.org/

Package: libpam-modules-bin
Status: install ok installed
Priority: required
Section: admin
Installed-Size: 227
Maintainer: Sam Hartman <hartmans@debian.org>
Architecture: amd64
Multi-Arch: foreign
Source: pam
Version: 1.5.2-6+deb12u1
Replaces: libpam-modules (<< 1.5.2-5~)
Depends: libaudit1 (>= 1:2.2.1), libc6 (>= 2.34), libcrypt1 (>= 1:4.3.0), libpam0g (>= 0.99.7.1), libselinux1 (>= 3.1~)
Description: Pluggable Authentication Modules for PAM - helper binaries
 This package contains helper binaries used by the standard set of PAM
 modules in the libpam-modules package.
Homepage: http://www.linux-pam.org/

Package: libpam-runtime
Status: install ok installed
Priority: required
Section: admin
Installed-Size: 876
Maintainer: Sam Hartman <hartmans@debian.org>
Architecture: all
Multi-Arch: foreign
Source: pam
Version: 1.5.2-6+deb12u1
Replaces: libpam0g-dev, libpam0g-util
Depends: debconf (>= 0.5) | debconf-2.0, debconf (>= 1.5.19) | cdebconf, libpam-modules (>= 1.0.1-6)
Conflicts: libpam0g-util
Conffiles:
 /etc/pam.conf 87fc76f18e98ee7d3848f6b81b3391e5
 /etc/pam.d/other 31aa7f2181889ffb00b87df4126d1701
Description: Runtime support for the PAM library
 Contains configuration files and  directories required for
 authentication  to work on Debian systems.  This package is required
 on almost all installations.
Homepage: http://www.linux-pam.org/

Package: libpam0g
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 215
Maintainer: Sam Hartman <hartmans@debian.org>
Architecture: amd64
Multi-Arch: same
Source: pam
Version: 1.5.2-6+deb12u1
Replaces: libpam0g-util
Depends: libaudit1 (>= 1:2.2.1), libc6 (>= 2.34), debconf (>= 0.5) | debconf-2.0
Suggests: libpam-doc
Description: Pluggable Authentication Modules library
 Contains the shared library for Linux-PAM, a library that enables the
 local system administrator to choose how applications authenticate users.
 In other words, without rewriting or recompiling a PAM-aware application,
 it is possible to switch between the authentication mechanism(s) it uses.
 One may entirely upgrade the local authentication system without touching
 the applications themselves.
Homepage: http://www.linux-pam.org/

Package: libpci3
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 124
Maintainer: Guillem Jover <guillem@debian.org>
Architecture: amd64
Multi-Arch: same
Source: pciutils
Version: 1:3.9.0-4
Depends: libc6 (>= 2.34), libudev1 (>= 196), zlib1g (>= 1:1.1.4), pci.ids (>= 0.0~2019.11.10-2)
Description: PCI utilities (shared library)
 This package contains the libpci shared library files.
 .
 The libpci library provides portable access to configuration
 registers of devices connected to the PCI bus.
Homepage: https://mj.ucw.cz/sw/pciutils/

Package: libpcre2-8-0
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 685
Maintainer: Matthew Vernon <matthew@debian.org>
Architecture: amd64
Multi-Arch: same
Source: pcre2
Version: 10.42-1
Depends: libc6 (>= 2.34)
Description: New Perl Compatible Regular Expression Library- 8 bit runtime files
 This is PCRE2, the new implementation of PCRE, a library of functions
 to support regular expressions whose syntax and semantics are as
 close as possible to those of the Perl 5 language. New projects
 should use this library in preference to the older library,
 confusingly called pcre3 in Debian.
 .
 This package contains the 8 bit runtime library, which operates on
 ASCII and UTF-8 input.
Homepage: https://pcre.org/

Package: libperl5.36
Status: install ok unpacked
Priority: optional
Section: libs
Installed-Size: 28863
Maintainer: Niko Tyni <ntyni@debian.org>
Architecture: amd64
Multi-Arch: same
Source: perl
Version: 5.36.0-7+deb12u2
Replaces: libarchive-tar-perl (<= 1.38-2), libcompress-raw-bzip2-perl (<< 2.103), libcompress-raw-zlib-perl (<< 2.105), libcompress-zlib-perl (<< 2.106), libdigest-md5-perl (<< 2.58), libdigest-sha-perl (<< 6.02), libencode-perl (<< 3.17), libio-compress-base-perl (<< 2.106), libio-compress-bzip2-perl (<< 2.106), libio-compress-perl (<< 2.106), libio-compress-zlib-perl (<< 2.106), libmime-base64-perl (<< 3.16), libmodule-corelist-perl (<< 2.14-2), libstorable-perl (<< 3.26), libsys-syslog-perl (<< 0.36), libthreads-perl (<< 2.27), libthreads-shared-perl (<< 1.64), libtime-hires-perl (<< 1.9770), libtime-piece-perl (<< 1.3401), perl (<< 5.22.0~), perl-base (<< 5.22.0~)
Depends: libbz2-1.0, libc6 (>= 2.35), libcrypt1 (>= 1:4.1.0), libdb5.3, libgdbm-compat4 (>= 1.18-3), libgdbm6 (>= 1.21), zlib1g (>= 1:1.2.2.3), perl-modules-5.36 (>= 5.36.0-7+deb12u2)
Suggests: sensible-utils
Breaks: libcompress-raw-bzip2-perl (<< 2.103), libcompress-raw-zlib-perl (<< 2.105), libcompress-zlib-perl (<< 2.106), libdigest-md5-perl (<< 2.58), libdigest-sha-perl (<< 6.02), libencode-perl (<< 3.17), libfilter-perl (<< 1.60), libio-compress-base-perl (<< 2.106), libio-compress-bzip2-perl (<< 2.106), libio-compress-perl (<< 2.106), libio-compress-zlib-perl (<< 2.106), libmime-base64-perl (<< 3.16), libstorable-perl (<< 3.26), libsys-syslog-perl (<< 0.36), libthreads-perl (<< 2.27), libthreads-shared-perl (<< 1.64), libtime-hires-perl (<< 1.9770), libtime-piece-perl (<< 1.3401)
Description: shared Perl library
 This package contains the shared Perl library, used by applications
 which embed a Perl interpreter.
 .
 It also contains the architecture-dependent parts of the standard
 library (and depends on perl-modules-5.36 which contains the
 architecture-independent parts).
Homepage: http://dev.perl.org/perl5/

Package: libpopt0
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 245
Maintainer: Håvard F. Aasen <havard.f.aasen@pfft.no>
Architecture: amd64
Multi-Arch: same
Source: popt
Version: 1.19+dfsg-1
Depends: libc6 (>= 2.33)
Description: lib for parsing cmdline parameters
 Popt was heavily influenced by the getopt() and getopt_long() functions,
 but it allows more powerful argument expansion. It can parse arbitrary
 argv[] style arrays and automatically set variables based on command
 line arguments. It also allows command line arguments to be aliased via
 configuration files and includes utility functions for parsing arbitrary
 strings into argv[] arrays using shell-like rules.
 .
 This package contains the runtime library and locale data.
Homepage: https://github.com/rpm-software-management/popt

Package: libproc2-0
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 232
Maintainer: Craig Small <csmall@debian.org>
Architecture: amd64
Multi-Arch: same
Source: procps
Version: 2:4.0.2-3
Replaces: procps (<< 1:3.3.2-1)
Depends: libc6 (>= 2.34), libsystemd0 (>= 209)
Description: library for accessing process information from /proc
 The libproc2 library is a way of accessing information out of the /proc
 filesystem.
 .
 This package contains the shared libraries necessary to run programs
 compiled with libproc2.
Homepage: https://gitlab.com/procps-ng/procps

Package: libpython3.11-minimal
Status: install ok installed
Priority: optional
Section: python
Installed-Size: 5212
Maintainer: Matthias Klose <doko@debian.org>
Architecture: amd64
Multi-Arch: same
Source: python3.11
Version: 3.11.2-6+deb12u6
Depends: libc6 (>= 2.14), libssl3 (>= 3.0.0)
Recommends: libpython3.11-stdlib
Conflicts: binfmt-support (<< 1.1.2)
Conffiles:
 /etc/python3.11/sitecustomize.py d6b276695157bde06a56ba1b2bc53670
Description: Minimal subset of the Python language (version 3.11)
 This package contains some essential modules. It is normally not
 used on it's own, but as a dependency of python3.11-minimal.

Package: libreadline8
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 475
Maintainer: Matthias Klose <doko@debian.org>
Architecture: amd64
Multi-Arch: same
Source: readline
Version: 8.2-1.3
Depends: readline-common, libc6 (>= 2.33), libtinfo6 (>= 6)
Description: GNU readline and history libraries, run-time libraries
 The GNU readline library aids in the consistency of user interface
 across discrete programs that need to provide a command line
 interface.
 .
 The GNU history library provides a consistent user interface for
 recalling lines of previously typed input.

Package: libseccomp2
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 148
Maintainer: Kees Cook <kees@debian.org>
Architecture: amd64
Multi-Arch: same
Source: libseccomp
Version: 2.5.4-1+deb12u1
Depends: libc6 (>= 2.4)
Description: high level interface to Linux seccomp filter
 This library provides a high level interface to constructing, analyzing
 and installing seccomp filters via a BPF passed to the Linux Kernel's
 prctl() syscall.
Homepage: https://github.com/seccomp/libseccomp

Package: libselinux1
Status: install ok installed
Priority: optional
Section: libs
Installed-Size: 199
Maintainer: Debian SELinux maintainers <selinux-devel@lists.alioth.debian.org>
Architecture: amd64
Multi-Arch: same
Source: libselinux (3.4-1)
Version: 3.4-1+b6
Depends: libc6 (>= 2.34), libpcre2-8-0 (>= 10.22)
Description: SELinux runtime shared libraries
 This package provides the shared libraries for Security-enhanced
 Linux that provides interfaces (e.g. library functions for the
 SELinux kernel APIs like getcon(), other support functions like
 getseuserbyname()) to SELinux-aware applications. Security-enhanced
 Linux is a patch of the Linux kernel and a number of utilities with
 enhanced security functionality designed to add mandatory access
 controls to Linux.  The Security-enhanced Linux kernel contains new
 architectural components originally developed to improve the security
 of the Flask operating system. These architELF          >    @4      @       0Q         @ 8 	 @                                 @$      @$                    0       0       0      a      a                                        '      '                   J     Z     Z     8      @                   K     [     [                              8      8      8      $       $              Ptd   )     )     )     $      $             Qtd                                                  Rtd   J     Z     Z     0      0                      GNU ˪9%@`-3    C   F      	   ( . A 0 TH	  f ( 0}J:    !  JR
    F   G       H       I   J       K       L   M   Q   V       W   X       [           \   _       `   b   d   f   g   h   i                   j       l   m   n           o   q   r       s   t       u   v       w   x   y       {   |   }                        kbwe~K1dr4ziaQw)`rNtWX|:Bm_^yzP$"KXgrB#هѿ1(nP$ir*r?e[
NwMP$id=Uk{	E<kk#mx03akN>;4"vz re
~uqdgR᮴P$_mP$gBSմDt	"{3^dy]{6irtyT5NeL                                                                                                             {                                                                                                                                                                              u                                            G                     }                                                                                     U                                            y                                                                                     4                                           A                                          v                     3                     m                                                                   :                     f                                           X                     Y                                                                N                                           t                                                                 "                                          l                                                                                                         &                     n                     .                                                                                                          ,                       a                     \                                          F   "                                                                                                           
             e    `V                
      l          
 p     n       h                     
                  y                 [                
             2          ^          
 @           h   
 `     I       m    V      D       #                -   
      2      3   
                 [                               v     \      N      *                    
                 p      v       T   
 `              
 @                                      R           0      Z      v    V             H          ;           `      [          
                
       *                 <      G                 L   
      )       =   
 @            =   
       6       k   
                       Z       Z   
             
   
 0     &          
 `                      9                 1       X    0V      0       y          S           @      1           W      %          
                  W            ;          .           @                 @                 `                 p      1       &   
                         1                 1       W          r           [      )                 a                 W       G   
             z   
       f           0      0          p      Y           [                                       _       __gmon_start__ _ITM_deregisterTMCloneTable _ITM_registerTMCloneTable __cxa_finalize __stack_chk_fail memcpy calloc pwrite __errno_location lseek writev getpid ftruncate mmap madvise strlen malloc strcpy fcntl mdb_midl_free munmap pthread_key_delete sigemptyset sigaddset pthread_sigmask pthread_mutex_lock pthread_cond_signal pthread_cond_wait pthread_mutex_unlock sigwait memcmp pthread_mutex_consistent pthread_key_create pthread_mutexattr_init pthread_mutexattr_setpshared pthread_mutexattr_destroy pthread_mutexattr_setrobust pthread_mutex_init fstatfs pread uname strtol memset mdb_midl_shrink pthread_getspecific pthread_self pthread_setspecific mdb_midl_search mdb_mid2l_search mdb_midl_append mdb_midl_sort mdb_midl_alloc __sprintf_chk stderr __fprintf_chk mdb_midl_append_range mdb_midl_need memmove mdb_mid2l_insert mdb_mid2l_append mdb_version mdb_strerror mdb_cmp mdb_dcmp mdb_env_sync msync fsync fdatasync mdb_txn_renew mdb_txn_begin mdb_txn_env mdb_txn_id mdb_txn_reset mdb_txn_abort mdb_env_create sysconf mdb_env_set_mapsize mdb_env_set_maxdbs mdb_env_set_maxreaders mdb_env_get_maxreaders mdb_env_open strdup mdb_env_close mdb_cursor_get mdb_midl_xmerge mdb_get pthread_cond_init posix_memalign pthread_create pthread_cond_destroy pthread_mutex_destroy pthread_join mdb_cursor_put mdb_cursor_del mdb_txn_commit mdb_midl_append_list mdb_cursor_open mdb_cursor_renew mdb_cursor_count mdb_cursor_close mdb_cursor_txn mdb_cursor_dbi mdb_del mdb_put mdb_env_copyfd2 __fxstat mdb_env_copyfd mdb_env_copy2 mdb_env_copy mdb_env_set_flags mdb_env_get_flags mdb_env_set_userctx mdb_env_get_userctx mdb_env_set_assert mdb_env_get_path mdb_env_get_fd mdb_env_stat mdb_env_info mdb_dbi_open strncmp mdb_stat mdb_dbi_close mdb_dbi_flags mdb_drop mdb_set_compare mdb_set_dupsort mdb_set_relfunc mdb_set_relctx mdb_env_get_maxkeysize mdb_reader_list mdb_reader_check realloc libpthread.so.0 libc.so.6 liblmdb.so.0 GLIBC_2.3.2 GLIBC_2.12 GLIBC_2.2.5 GLIBC_2.3.4 GLIBC_2.14 GLIBC_2.4                                                                                                                                                   V     @   ri	   }             ui	           f         ti	                ii
        ui	         Z            4      Z            4      Z            #"     Z            !     Z            -"     Z            7"      [            (#     [            X#     [            #     [            #      [            #     ([            0$     0[            p$     8[            $     @[            $     H[            $     P[            0%     X[            %     `[            %     h[            &     p[            H&     x[            &     [            &     [            '     [            P'     [            '      `             `     _                   _        "           _        =           _        A           _        D           ]                   ]                   ]                   ]                   ]                   ]                   ]                    ^        	           ^        
           ^                   ^                    ^        
           (^                   0^                   8^                   @^                   H^                   P^                   X^                   `^                   h^                   p^                   x^                   ^                   ^                   ^                   ^                   ^                   ^                   ^                   ^                    ^        !           ^        #           ^        $           ^        %           ^        &           ^        '           ^        (           ^        )            _        *           _        +           _        ,           _        -            _        .           (_        /           0_        0           8_        1           @_        2           H_        3           P_        4           X_        5           `_        6           h_        7           p_        8           x_        9           _        :           _        ;           _        <           _        >           _        ?           _        @           _        B           _        C           _        E                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           HH/ HtH         5- %- @ %- h    %- h   %- h   %z- h   %r- h   %j- h   %b- h   %Z- h   p%R- h   `%J- h	   P%B- h
   @%:- h   0%2- h    %*- h
   %"- h    %- h   %- h   %
- h   %- h   %, h   %, h   %, h   %, h   %, h   p%, h   `%, h   P%, h   @%, h   0%, h    %, h   %, h    %, h   %, h    %, h!   %, h"   %z, h#   %r, h$   %j, h%   %b, h&   %Z, h'   p%R, h(   `%J, h)   P%B, h*   @%:, h+   0%2, h,    %*, h-   %", h.    %, h/   %, h0   %
, h1   %, h2   %+ h3   %+ h4   %+ h5   %+ h6   %+ h7   p%+ h8   `%+ h9   P%+ h:   @%+ h;   0%+ h<    %+ h=   %+ h>    %+ h?   %+ f        H=+ H+ H9tHn+ Ht	        H=+ H5+ H)HH?HHHtH=+ HtfD      =Q+  u/UH=+  HtH=2+ ]h)+ ]        {f.     HVHOHH9r@ HVHO9rfD  HLGIHN    I9sBqHH)tff.      LGHH?HNI8H)HH~'I   f     BqHH)uL9wHHHI     AWHAVAUATUSHHXH|$BHT$(LtHdH%(   HD$H1E~AV
ADft$$DnHq0HNH5HL$H9  f   HL$0HL$D9~r1E1E1H\$(HtT$$1!ȉHD$D;|$$fxH      LCHD$HdH3%(   p  HXL[]A\A]A^A_ÐAoA9|LBT- Ht$HEdFIMAD$HD$0ID$HD$8HD$Ѕ   EoA9}H\${B   ADAF
 (DEdNM    HL$EfHQ(M2Ht$0D9   HD$0HD$ AoD9Ht$0AT- HHcIHHt$IDHD$8HD$ЅtEo@ H\$D{B    SAvH
fA|6H5HDHt$+11E1CD6fD  USHNV)ftF
 tH[)]fD  Ht$ Ht$͉HH)[HH]}ff.     fAWAVAUATUSHx  HOHHo H|$0t$DHdH%(   H$h  1ۍ^HL$(HD$ D$t$@\$XE  EE1E1E1HD$    E1E1D$HcHD$PHHȹ   HD$HHD$HD$`HD$8r@ Ht$Dd$ǃHvfA
IHt$tAGLH9L$u|uxK!H   @wkIcAHHL$ILdhL|`LHD$A@9\$|HD$LxAG
f mf%fAG
HD$H@    D  Eu#9\$t  Lt$LA   1x@ \$\Lˋ} Au     uD} 1L?HtHt$8} DH9  H   t H$h  dH3%(     Hx  []A\A]A^A_    Ht$`LHfD  Ht$ 9Q  HcL$@H\$(HHIHHHHHtD  HfA
H9t3HJA
f tf%oBHfA
GHHA H9u͉|$@D$ \$@HL$0)   HD$(H1
D$X9D$    t$DHD$ Ll$(Ld$HDt$@HD$PHI\ t&=D  II9tOI|$ I|$t"G
uH   HH   f     AFAoL$HIHLHDt$@D$ -D$@$\$\   >D$D     USHHoO9uC    H[]ff.     fSHHHH)H~.   HvH
uHHHI[fD  ff.     BHDB   H       E1HǇ      H  PHǇ     HǇ      HHGHH  H      H  HO@HfDH  Bt0@   f    B ff  Ƈ  8HKH9  tÐ  uHH       o   oH  oP H       HG@HGH      D  H
7HRHT0uH
H5THDH1HOt tHHHDHG @HHHDHGfD  AUIATLcUSH8dH%(   HD$(1HA}f1Hډ))C$   Ld$HD$   t'R tHL$(dH3%(   uH8[]A\A]Ãu1f<$     AVAUATUHSHDwt1IIM)IHtzEt:[L]A\A]A^fD  L   MtDI$H   L[]A\A]A^D  J<(L11fAD$L[]A\A]A^fD  LA   Iy뇐   AUIATLcUSHD  K\ HuJ   IHIPHPIPHPIP(HP(IP8HP8H@HtIPHPLHtIHHL@Mt]uHǹ1   LHH@HtI  >   HHLhHuKD     IEMH[]A\A]fIf.     AWAVAAUAATAUHSHDxLo HWpAGHc؃.        HuXI   Df
 fYH~gtH[HEuI   HxHtH@    H     I   H$1fXI   HxH$    Et
E;}   E|   t_HUHHt&HAE tA    tB    HEH    Ex    A E|E   H[]A\A]A^A_       M   A   AE   H       HExHE H  `|o   A H@    H}(A     H}@  H}HvL  E_HH[]A\A]A^A_O    E}     A      uxH}h1>D  HUHL}    Hu0   D  t1L$H$L$H$9   HH|G
uI   HI   fD  H}(7  HE(I}@Iǅ       Iǅ       I   IE`    Ht	H@HL[]A\A]A^A_Ƨ  fD  H    h@ AWAVAUATUHSHH_ Do|L{@A   n  ME  C   LgHDC(M  AD$D9=  I$H/  1@ IG0I$I$IG0H9uI$LeHHEHLdAoD$HEX    AoL$(HAoT$8P Ao\$HX0Aod$X`@Aol$hhPID$xDm|HHEC ExvBD  H   HIHHHUXAffAfDBHUp
9}xwHEp@HEp C	  HEE1H9   sAHHD[]A\A]A^A_fD  Mt+I@j
  IG0HHLd+D  HCPLcHI$   H   H9LBI$   HS$H}`HE    HEH   HE0    H   HHEHE8    ǅ    H     H   HE(H     HE@    Hk`18 AD  HCPLcHI$   H   H9LB1I$   HGH    HG    Hs@HH@&  AąfD     uDC(IMSHC@   HH$u/D¾   HDD$AąOǃ      DD$H<$DD$DD$  DD$A81DKDD$u'   9   AMfIMAt$uA9.  LHLǂ       Hǂ   H   ICH<$ME   s    t   Lfƅ\Aǆ       AYD9   LbHLIǂ       MHǂ   H   WAW8AbH4$HDD$l  DD$AAEt0AǇ       M      IǇ   I      H<$A AWAVAUATIUSHH(HG HT$HL$HD$G|  
 upH,6IA   Mm AMtSI}@M}HHtH辡  Iu@H;wH;,tmI? tHL  I;wHIH;uHYfI;\$sKHD$E1pHHX8HD$HT$H1HtD2H([]A\A]A^A_HD$pHHX8AL$|ҐAVA    AAUIATUSH LgdH%(   HD$1GD@Et$xLDDfMtABDu$MMu   ID$hUHL MD  AP@tDJI@HK|PfHQ
ցP  9u	f fQ
HH9uI@Ht@DtA
tCHH  TQDiIE   Et{Lt$
 A9l$xvgIT$ptH@HID$XHp(HtI}HT$Lu0HT$B
P  9u|$f fB
A9l$xw1H\$dH3%(   u
H []A\A]A^ff.     SHHdH%(   HD$1FFH
HDu$H1H\$dH3%(   u1H[f     HH01HuH$HQHIf     OD1  AWAVIAUATUSH(HG( Lohv
IEX@6HtIE HxHHD1HH1A;   e  IEHIu@HD$H  Hǅ      HuDAJL9sH      L,  ?  ?  CŉD$HD$H ÅK  IE@HD$    HHD$L`fAD$
 u`H0Im L<6Ht6    H}@HtL距  HM@H;w
L;<   Hm HuH|$L     l$tD$vAI}@肠  DLuSD  L#AM|҃	AU|H([]A\A]A^A_        fAL$
 fD  AM|   	AU|H([]A\A]A^A_ÿ 8  IE@H   1tE1JD  AWAVAUATIUSH(HL:DjHK H    tH; t1H{(DL袞  u
I$L)h1H([]A\A]A^A_D  HIHS@E
uHHL$HtK4?HHT$Ht$   HT$AH;wHt$H;4HL$u
    E1H   DDD$HT$HL$ל  kDU
HL$HT$DD$A1  LCHI8HGI HLHPH0H9tT@  DOIHKOLI)     HI9  HHPIH0HxL H9uڃ   Au-A   }   HHL$,HL$    H   H7AD5 Hυu H4D@Ht_DH1I9w9s/)IWHH@ HLHIHqH9uL/f     L;t*JqD H   HE H   QILEIS  H  H59  Hx &  fD  USHGBDGH  H\HCAfA9  K
AЉf    ADSHH؃Pjur1A    fA9tLCf9vDfLSHfA9ws׉HH)Hc׉HJfkfkH[]f.     @t2jD  )u&AfkfDSH[]    (OHcHcH|HcHDSHG  H]  H5  Hx Ͳ  ff.     fSHH dH%(   HD$1G~uBHK  HH{HHt$HH$Ѕu+   HD$dH3%(   u0H [D  Hٞ  H{ O  H  H5_  ;  vfD  AWAVAUIATIUSHH(HL HT$L4 f     H{@Ht!L  HC@H;(wH    L94tHHu1H([]A\A]A^A_D  A$         AE
tAUAGt/I9twLLHD$fAM
L(H(1[]A\A]A^A_I|$ It$|HL$T$HHttT$EGHL$~/ALHL$OHL$IID$@H;(t1HuLDHL$HD$,H|$HL$IIHH(B   f.     USHdH%(   HD$1G@fk  HfG@GBfGBH<GH     f   fH  HDHH{@
1  SH  I1TPHpP H HH	LH	   S@H$f   rfSBfs@1HLHfSH  uASBfSH  1HL$dH3%(      H[] HDHDApA9sfH  "fD  Hu"SBHDH @ cDf.     fCBfC@siHSJ|>EH   H  H5N    f     t$Ox  wH HH  H  ÉIHHvHHIAPH@ IHIHvHHIAPH@H9t	L@ H?HELHDff.     GA
      |   Ht4   tM   HwpH8tIbD HD       u+   t%   ҃븋?   tuE1HD D@ tff.     fHtG|%  =  t   fD  [ff.     AW   AVAUATUSH(GHL$AA   A	D!ø
        HIH  F|A	A 
   Dk$9A   Aǘ   Mc   L$LIH>  H   L$MEf|MnXIFPE$In I)MM~pMW  H@    HIIA`MnhIF`L$HIFH   L$跒  IF(H  L$I~XIAIqXIFA   A   IFHH     IAAI|IFAAxMqMH@IF@    HAFxAFxL$tIApINpA9^xwo   H   A   Ht;HL$  H   HH  I      HcL$IAhAQxHD$-  LcIE  HD$N    JHtH{O,MIIIx  uD  1   HHL$HINXLT$HCLsLL[HK(INpLMHK8tH  >   LHMsINhLH1H3HHHHLLT$L$HvfD     L[   L9uhtL$u$H([]A\A]A^A_ H   IF`LuHD$E	f|L0H(1[]A\A]A^A_@ A   tGDk$1A   Aǈ        %   H(%[]A\A]A^A_    Lwhz    I~HL   ;   1 HtHG fD  1ff.     fHtHGfD  1ff.     fHtG~u@    fD  Ht#UHHHtH"   ]     ATSHdH%(   HD$1D$    H  HGH@|J    H=  IԉHcHH
"  SD   MtMtHLCMt:{BL{H|HEH  GA9c  fAH  fD  u+Ht$dH34%(   x  H[A\H
  y SDM  H{   H      LD$LLDH  SD늋SD   MyHK(AfT  H{GD^  SDBLH  SD/SD   KBH|HG>  DKH  MA9)  G
   HC( LHJDHF1SD   MHK(AHK1qDyBLA(HtHFHAEIt$M$fyH  1LLH	  SD9LHv  SD&Mt.HC(@   SDLH3  SDSD   
D     fD  fKH  fD  FLOIAAuuHtAAHIAHFLIL$LH0SDp     	   LH  HKSDAD:0   A@D1LLыSD	LH  1rHKSDNMcBDOHHtGHHGHF1MGtH{1ҹ   LSDLHIL$H/SDofAWE1AVIAUATLcUSH  Lo HT$M   dH%(   H$  1MtEA	  HD$A   H       Ak<E11DD$    D$AD$D$9\$   E  HT$(HHT$(H9r~L$x  IFHhIF Hp@HtEHcN8σx:HcHHHHHH)Hfpt
H0H9HGH@H9uI   H9  D$   H|$P1Ht$0DH|$eH|$]  HD$8H0Ht$(H9   D$  IFHhIF HH@HtKHcQ8AAx>IcHEHHIHL)HD  Ht
HH9HGH@H9uI   H9N  D$   $   HT$@HL$HHĘ   D  DFH  H\$HH3M  I   Z    M   HD$(HLI     AA   9\$A   D\$I4E)f     BHD9t|HAJ<I9<uAىAE   AmHIm8  DȉD)D)I?9  BIfD  CHHIHBA9us  @ l$eD  AINIc1HI;      AEpI~ Iv|DHL$DL$vDL$HL$HHK      fD  I   11H|$PLDT$I   HD$(W
  HT$(DT$HHD$(A   HD$0   HD$8fD    I   IH;qAN|H$  dH3%(      H  []A\A]A^A_D  IF0HHP0H\$An8IV0H1ff     IMfHM HL:HD$H(1uA=x] AVAUATUSHH0LgdH%(   HD$(1GBHlHE
utAD$|t+HT$HLHD$    Ku%Ht$H   I|$(   Z    AL$|HL$(dH3%(     H0[]A\A]A^ I<$ =  @5  Mt$HLm I>   I|$ It$|   >HD$H  Ht$LLl$HD$y  k  H|$ID$ HPHt$fN
L.SB{ ID$hHtHHHCD  H   {@HL    H Htxf9x@rH9tHH9jHuHrHF
tHPHtBDtDNFT@AAE9sFLVIEQAfAuEQOLLJHf.     1f     H{HT$   cH|$7L/L9m +  IT$(HHHHM HCBf   HHTHCH  DBHLH 0fPLL蕈  IH9wCHIL9*u61H9jcDAL$|fD     fD  H HC	  HS  H5A  Hx ˜   H{@HD  H HHPf9z@rHH9jHuHrH HC(Lh(HC	  H  H5  Hx V  HC	  H  H5^  Hx 6  fD  AVAUIATUSAHAH dH%(   HD$1GBHTHHT$   fDpCDtKBfD9KH    AH{9  ALD$1DBHrBHH H	LH	o  CBHT$fDCH  C@fn  HfCBfK@HTH1fCH  @+  HT$B
   s tBM  Et&B@1E1*f     HT$LHHt;CBL$DCH  ufE%  AHT$BD  HT$BDpf        CDCD1H|$dH3<%(      H []A\A]A^f     C@PfCBHDHfS@HD$@D  H@uCBHTHHT$HCH|H   H*  H5a  Ι  HCv  H  H5?  Hx 讙  HCH|2HC  H׽  H5  Hx w      UH1HdH%(   HD$1GBIHDHHPH$HpP H HH	LH	uEEB1H$fEH  E@fw?HfEB1HfM@HTH1fEH     HL$dH3%(   uH]HEH|    AVAUATIUH  HwdH%(   H$  1F|  HG8HA uoHE(Hp(H  H  HEHHtH90tH}1HUHuQE@   A   1Au8DLH(f     HF W H~`H   ć9t)H$  dH3%(     Hĸ  ]A\A]A^ Lt$ 1ɺ   L  Hu01LuHu0HT$LD$    9T$   Pft(ufD  HhZ HT$HL$HL:HU(HL$Bf%f9AuooIJoQ R HE8 p    fD  HE
  H)  H50  Hx 艖  f     LNXW L@HFpH    IHG    MLFPHwLG0E1LO(HG8fDH  HG@    HGH    AA   H   H  HOHA(H  HA0H  HA8H       HA@HG0Q HPH@ HA    HqH  HG8Hǁ      Hǁ      H  Hǁ       t   1@ HG     uPH~   H  H5  U  D  AUATIUHSHHHGHt`DH     H#E@H       H9   uBHTHJ
   EDDjED1 fuH     IMt-AE   H}Hu(LH}1LTuHtAEIUHSH1H[]A\A]fD  1   HRH[]A\A]fD  HE(H HSHH1[]A\A]fIL$LLHuHE`  H  H5  Hx   AWAVAAUIATIUHSHGDt		    MBH\Ht"SMH  9  EDHE(@   ED6  EBHtE CH  9  fH  C
     EBEH  DCHC  Mt/IMLHH}u1CtH}1LuMtCHI\$I$1H[]A\A]A^A_f     MH  D|CIAG   AFH}1ҹ   LAu=uMtAWIM|$I${ EDC
 HE(EBEH  I$HHDID$H1[]A\A]A^A_f     HLLH[]A\A]A^A_@ HE`DA	=@    Hu'EBH\HKH}Hu(Hg MDHE!  H_  H5
  Hx O  ff.     @ AWAVAUATUSHHdH%(   HD$81H> 9  HGHIIՉMHt`DED  HEH    1LH>   EBLDHA@
L  LLHLD$MLD$ItA$>  M  AP
ED ED  AGx  Mt/C  HEHt`DIMLLHu$1wAWIM~If.     H\$8dH3%(     HH[]A\A]A^A_D  UBLDHA@E  A@
 $  HE(E1 HD$ I@HD$(HE0LL$ LD$LLL$LPLL$LD$g     A@  AA@
 6  HD$ ID HD$(HE0L$LLLD$LL$PLL$LD$L$EB	    DEc  Ax   HHD@UF  @9HH9uA9  fD  v`1ExMAGHD$ IGHD$(f}B 1fH  uMfD  >fD  HE(EBEH  IHID IF1    EB1fEH  MtA$   g@ H}Hu(LMAGiCH}   E1u
D$     LD$ 1ҹ   LX1yf     EBl       H   EBLDHAP
  ExM    1LE|@MAGHD$ IGHD$(    EH  A@H9   A@
    HT$ IDHD$(HE0LD$LLPLD$   M MDw    LL$ HL$(LHLLL$KHE0H`LL$H@H9   LLЅtfoD$ 1AE     fEH  Mb    eDÇHcE|HMAGHD$ IGHD$(H|$ HHD]E1fBEH  21fUH  #趷HE  H6  H5  Hx V  HE  H  H5  Hx 6  fD  AUATUHH  dH%(   H$  1HD$    H¸   uQHtL9wxvGIHOpt8G|uRLl$H$  HL8LD$LH   L`H$  dH3%(   uHĠ  ]A\A]ø贶@ AUATIUHSHHHGHt`DH     H#E@H       H9   uBHTHJ
   BfuH  MD    DlBIMt-AE   H}Hu(LH}1LNuHtAEIUHSH1H[]A\A]     1   HJH[]A\A]fD  HM(	HHHDHCH1[]A\A]fIL$LLHkHE  Hì  H5  Hx    AWAVAAUATIUHSHHGD,  WBWH  HK(LlHA   cDf0  fSH  AE
 U    CBCH  ADEIAE  Mt3IL$LLHu4AEtH{1Lu HtAEILmHE 1H[]A\A]A^A_ÐE|MMAG   AN/H{1ҹ   LA  =  SBSH   ;uCBHCHH  fH  fD  1HNSBLlHAEfSH  AE
 HC(CBCH  HU HIDHEH1[]A\A]A^A_    HKaDA
9@ H{Hs(LؾMdf.     HtAWIL}HU cDyHCt  HI  H54  Hx y  f     AW   IAVAUATU1SH  dH%(   H$  1u?IGAO@HD$ AGDtif  fAO@fQ  fAoBT@ =    DAgDH$  dH3%(   E  H  []A\A]A^A_D    (  1Ld$@ITHITHH9wHD$ H(HD$IG(HD$(HD$8HD$AGBMtHAVAF
  &  ZA   H#    t   DIL9   CTnLBtBI1HtHT$Ht$}   HD$8Ht$@
  PH|$l  uXIW(HD$8@H)BuzAG@fY  1fAH  fD  IG(Hp(HD$ Hx(k  wfH\$ K|gfIHt$(BI1uDIL9 uIG(Hx oD  AGBfzfAGH     L4   fA@ cK H|$։T$j  PT$tHD$ INHp(BI|F DHHMA@EXE HI L	L	LCLJH9uI=AG@ffAG@ft`1fAoBfAH  f        1fAGH  ITHITHH9wqIW(Hz 1AgDfAH  6AGD*IG&  H  H5Q  Hx 节  ŮD  USHH  dH%(   H$  1G    HW8!   HwHF H~`H   ć9t.fD  H$  dH3<%(      HĘ  []    H   H$  H`Hs0   H/uHC8@ 1fCB1f{@ tHu%D  sBK@VfSBf9sHtK@fKBP諭ff.     AUIATAUDSHHHdH%(   HD$1Hu8H$fJ
   fJHKHI IfJ@t-HK(HAIU H\$dH3%(   u;H[]A\A]D  @utHK(IcHqDb@ HK(HAAWAVAUIATIUSH8L$dH%(   HD$(1GBHD$     H\H{Sf9h  C
EΉAfA urIω)HM   M$Ipf  Ma  A  IL0IuHt$Hv D   M9`  MBIL   IE(Lc8)AMHLt  It$LLǬCfCD)fC1H\$(dH3%(   |  H8[]A\A]A^A_    f  A      H9-  DAAA9v;EKDHHLAHM)H)@ BtPHfpH9uD)HH9
  f|kf{H<fSM   I$fDwfWAC
   L$HDGI fDGIt$D$譫C
D$Ht|HD$ ELH   H HHD$ HxA   tCI1     IILAK<>LHca     IwI$1kD  1fDwfGC
   AHGT@ AHG&AZIGH H1D  I	IL<vH1IIDL$HLD$I9ȍPUHL$    LS{ALD$DL$L$1DI fDGIEHD$HD$H|p-IEo  HM  H5  Hx |  IE  H-  H5~  Hx |  IE  H
  H5  Hx |  ff.     fAWAVAUATUSHH  Ht$ HT$@   HL$HH$   DD$dH%(   H$  1HGH@ HD$8GBLdHGH  At$
Et$fD$6$  L$   AD${BfAEf)  DD$l    S@A@D$0C HKf$   Hs(f$  H$   $   HC0H$   H$   CDH$   $  1t,     LLHLLHDCH  fDEH  H9wHcD$0N  HǄ$       H   HD$DSfT   D$%   D$P  HD$ 1D$h    E1fBD  o D$6)D$HT$D$(D$)$   HD$H
IM H  Ff+FH9  C@$   f$  f$   fD$XH$   H@hL,$    H$   IIE 1E1HH$   IM} IIU   D$Xf;C@sD$0HcD$0HD$HD$H<H  HGHH9  HL$@D$X   LKAH  9rkT$01Jt,fD  HTHHTHEH  fCH  HHH9uHD$HwHD  fe
  D$X   fAH  D  L$P	  AD$
 v  SBE1E1Lt$PH$   H$   Hl$xMH|$`Dl$DHLHH$   HL$pI   HL$PIcTQLDZHzDH$   rL$   DJfa  LL|$pH$   :H$   	uHǄ$       HT$`MLHN  D;l$h+  AD;l$
  AD$
D;l$(EHL$ fDL$LE|$@LDt$HHQH$   HH$   SBfSH  ]AFfAt$Ht$8fAD$HcANVA|DAtF)LLդL$(9L$  CBLdHD$   t4SBHDHSH  TPH@uPHL$@HDHA AD$S AHCH@hHH&  H$   KD|$lHD$HD$L< LhH   HD$D$L|$ E%   D$fD  HЅtHBH9   rD#pD     DPBsBfD9wDDNM9`H`  DD$XEuED;T$0|NTN9T=
   AD$
tPL@MtGA@Dt@LLHpH  AA9s%ADqIAAfuAAIDI@HHH$MtH|$8H   IL   f     H$  dH3%(   
  $H  []A\A]A^A_@ H$         H66  C@ft'D  HT@HTHCF  fCH  HuH$   HC(11E1M$E1HHSHhHfDH  HP(UfP1|D$0@  L$   D$lC@PCBfS@xf{BD!fAAAFDt$hE|$AE
 :  H|$8GD$(hAD$
  HD$@   H0HD$ H HDII)LHH9HGDxAHy Hq|   DL$(衮DL$(HI	  I$A   IAD$
fE^fAF
HD$8@fAFD$6D$(E  DD$(Ay11)D  ƉȉAtTHfAtFHBH9G  HAA9uHcE1҃fETv H$   L$P  Ǆ$     H$`  H     BCH  DAt$AL$   L)M|D)AfA)D$EfAED)D)fAt$t$6fAELt$(9u	HD$ H@H$     ADEх  HD$ K|
LL$pDT$xHpLL$`LD$XLD$XDT$xDLL$`HE1LD)K4͟L$   L$p$  H$   AEfAE)fAECBfCH   $D  HCH|c EHI L	EL	IfCBHL$P1E1HLHLt$P$MtH|$8H   IL    HD$H$   I1f$  H$   E1HD  f$  D$XND$X$D  AvEID9  D$(A9  L$9  A9r  AD$
A   f|1ADl$XD\$(Mc1E)RD  ALFLDiAAU
AD$
tA  AU9  A9  L9  AA9uD@ L$(9L$ZCBH$   H|$HTHH{H  fH  HWHLH9   Q9H?J  H      H(H(T fHH9uf     L9`HHc DpH  fDpJ  LDHLDPHyH  D9@@fH  HsHf@@HpHpBDVfDPB@ CBDL$1HH$   LD$HHL$@HTH1fCH  HT$ \KB1EH  fCH  H9 NXL\$(EH  fD;T$6r|$ uAfEH  EE9L\$E)MXHL\$(fEH  EmE1fFEH  fF@H  NTHNTHIE9>fD  HD$ A
   H$H HD$(D$(DxAD;L$(ND1A   (D$xA9t@IcAfLf     Dl$XACD D$L$(9L$   HcD$$  L$   ADFLPHH$   H$   D  HCPI$HCHJ  fH  HC(fhHP(D$0$MLt$PHl$x    AVփJHfD  ATFfATDHHH9utHD$ $  L$   HH@H$   H$   lD$X   ILLD$`LMLDE1LL$XCBT$L$   LL$XLD$`CH  K<L)蛚HD$ LD$`LL$XHpLL͙AD$fAD$$  L$   )H$   fAD$LI}LDT$xL$pLD$`LL$XvDT$xL$pLD$`LL$XALT$ NLT$EH  fF;DSAfEH  1HfAH  17D$X   D1A   ECBH$   H|$HTHH{H  fH  HWHLH9   Q9H?J  H  D  H(H(T fHH9u$   `AVAUATIUSGBLHlHGH  AXLlE AEHHPHփ)Ӆ   IU}~)9   A؃ t*HEHtU@ f9rD)fHH9uHcH)HcHHH)9f)]AEM$HpL9tfD@Mu[1]A\A]A^ It$HxLG[1]A\A]A^@ DhHL1H II	I	ĵ[L]LLA\A   A]1A^FfD  AWAVAUATUSHH  dH%(   H$  1GBf@LdH  f~@H  H  EBE|$
HDHDXHD$AD$AAfD\$fA   1Lt$01  HLIyAMIUHT$(HL$ HEE AEA} HT$8LAUHH|$0HIH H	HT$ I	  CAA׃9H  D$DlSB48IfElC
bID$AL$@H|$@HD$XAD$ D$`ID$(HD$hID$0HD$pID$@H$   1t(D  ITHHTHADH  fGH  H9w݉t$HD$P    t$uK$   HĈ   @
   HT$hH
HD$(HL$ AMIUcDAO|H$  dH3%(     H  []A\A]A^A_    HS(
IT$HT$(HL$ tlH\$Dl$Lt$ DA   +@ HD$ DHD$(AD$D)ڃ9s!E1E11LH[tRfH\$fkB1H輲SBfSH   Hu"Ht$ HHD$     |  CBL{fCBLtHAN
Mt%S tI?   IWHH: [  fD  I(LM  sBAN
LCS H{(f  HoIxhHH   A{DDl$M   DFK4 LT$MHHt$L    I   L$ @ HЅtHBH9txs@f9p@rnJ4L9vH   NTN9T  ftKLPMtBABDt;HvHL|$F|xFA9sBD~HFf/  @ HHlDe@HE(DDhfEtAD$fE@f   fmBH  HU(JD)DfD9Ef]@f]B?    PHPHHD$(HT$ f.     LT$LVHfF H  FTEfFT@D  LT$N<EH  fF;TCAfEH  f.     L]     HofD  fCBeDFHDIBHLHLD$HT$FO  HT$LD$H;HHL;qL;rsBAN
LCS I0@I~0AG8Mw0fAN
]M͏HG  H  H5  Hx mc  HG  H  H5N  Hx Mc  ff.     fAWAVAUATUSHH8  DOBdH%(   H$(  1ELJTHHB
L_ DRfMA   IfACEHBAD))Hi  HHL9|AAE9  K@f  ANTHAB  C H$   H$   f$   $   HC(f$   H$   HC0H$   CD$   1 HTHHTHCH  fEH  H9wI   HTHHǄ$       FCH  BL   fB|K O  1fBL   ADBIArABHH H	AH	tA   KB$   E1fDT  HDH@fKH  H   HSp@HR )J)Hi  HHI9A9  HHJ{DsBACDfDCH  =f.     HkHU
@u#E  u  fD  E1H$(  dH3%(   
  H8  D[]A\A]A^A_Ð1fBL   ADBIArABHH H	AH	%AuD$   KBE1J   p@fDKH  HKHI )~fBD  I)Hi  HHI9	D9  I   AITC|$   fD   H$   H@hL4$   tH$  L$  Ǆ$     IHHIE M.$   $   AIE $   IH$   HC$   C H$   HC(H$   HC0H$   HC@1D  HTHHTHEH  fCH  H9wHC(E1Hu H(H@(fDXH@    F  AHCS C@    KDH@hHЉKDHu H HKDHtHPJDt{@f9z@rH9jHu̓B@    JDHu H(E  AiEH{1HpP H HH	HSHH	HC(Hp(迡A'HC(xHhDOfDHJ  AfH     fAv"HTPHTHCJ  fCH  H9HCS H@hHH{DHЅtHBH9t@Dt
H9hH  HHuH[AŅt.CBE#HA   :At
CBAHA  $   L   D  AV
   H$   E1E1HD$`    HD$h    HHT$PIDHD$XHǄ$       SBSH  HHTHB
7  f.  HCDs@f$R  H$  H$(  C DfD$P  $0  HC(H$8  HC0H$@  CD$T  1Et(D  HTHHTHCH  fGH  HA9w݉L$LD$H<$KH<$LD$L$A  $R  HX  @
 ;  H$8  H2HD$xHt$pAF1Ht$pL$f$P  f$R  fDX  "Ai  CBL$CH  Lt$PEHHL$`LkA2  t$PH$Ѧ$   ED$$   D$,HFT$HĈ     L|L$   HT$L|$0IIPhJD$   AH   HD$H   L    H$HHL\$8HD$ LD$@Ht$HDHЅtHB@D   f;HB   H9tL|$L\$0N;\  H9tL|$8II;H/  G
tXLPMtOABDtHL|$N\L<$F|xACA9s%CD{IACfuACIDIBHHHFLD$@Ht$Hft   U  T$,H   x
HcfT   '     HHD$XD$D$   L$(  H$  D$   f$R  $0  H$   D$T  DH$8  H$   H$@  1Et#HTHHTHEH  fGH  HA9w݃I@hAf$P  Ht$If$R  HtH$  L$  Ǆ$     HLDL$H$IL:<IH$DL$H
t  $   H   x
  CBЉHH4SfH   ,  fF   HTH  $   H   @
   HHT$XHC(Hkf$R  H$  DC s@H$8  D[DHC0H$(  D$0  H$@  1D$T  t$LTHLTHDCH  fDGH  H9wHEhAf$P  Hf$R  N<tH$  H$  Ǆ$     ILD$HE I/HU D$Iu!CBHTHB
  EACBALNIAd  ANEFIIH I	AI	fu	f  AVIFHD$XHT$PA>HHD$hH|$`1fEt$LDPLDHDHJ  fDHH  H9fh@fhBD$L$   HHD$I@hHHqD$   Ht$0L    HLD$ AL$HT$DH H   HtHPH9tBDtf;JBwL<$II;HuL\$NEH  fEK  D[BNDHMGHF[H  fAF  fEH  G
tLZMuACDjMHEH  AWA9KCTWIAWf0AWITISH     LD$ Ht$0EL\$ NL$F\   fE9H  D[BNDHMGHF[H  fAF  fEH  L|$ N8L<$EH  fF;T{HAfEH  7PHPHHD$xHT$pAfEH  $   HLD$$藺$LD$A&$   H   @
 S  H$   H9HD$XH|$Pf$   IFf$   AV/HƠ   HD$Dt   fǄt     Ht$pHD$p    M$   D$fDT  (H$   W  H|v  H5o  Hx ,S  BHBHHT$XHD$P9HHt$pHHD$p    HH  fǀH    ACBfCH  EHCv  Hu  H5o  Hx R  PHPHHD$XHT$PF~HHHHHD$XHL$P   Hu  H5rn  LNR  H$     Hzu  H5ln  Hx *R  f.     AWAVAUATUSH   dH%(   H$   1H  HH  HGHAIAHx H<$A     D$    @|  ,  HE HH=    HS(  BHDI9$  HD$p    EAA@#  Hz(  DL$H$   Ǆ$       A     H$   HHt$DL$AF  HC0Ht$HP  CBDL$AfCH  CDtCDA   u1LEtD$I$HT$`HD$`HH蛗A&  A·  HA  HC(HE  SBHDH@
   DL9E   SH  HuAH|LS}CBf  fSH     fCBfO  A   HSH  AHfCBf0  f: tHHfDcBACD  rHB    HS(t$BA %   EAᵇA
H$   dH3%(     H   D[]A\A]A^A_fD  CDE1Vf.     A        L$      HH踽ADL$At"u&fo$   AA$cD  AEA CDC@    A·CDD  H$         HAC@H$   f
  HE1fCBfK@HTHfDCH  HC(Hf@HP(HC8HC(Pуf  KDHM tH<$I4$   LDI9  D$    LD$     HD$    sBEA  H|HG
   Gf+GH9%  DDHH߃%  HDDEA   EEEA   D$   E1Dt	HC(H@ E
  EuFKDA     D$t$It$9t$o  SBI$Hs(ID$Dt$ HDH8ADD    HCH|I D$    HD$    SH  HL$(LHLEZIJEHL$0AzN<NDD$ L$   L$   tyL$H MIXLL$hLL$PLL$8I@  A@tLHC0H)|H@H9	  LT$ H$   LLT$ 	  A      Az D1@M<$  L9$     1H膗Dt$ HM LE1fL$HE   HDHL9HGHHHD  H$   fI
 KfD  AD  H<$D$    1A   LXfAwAG  HǄ$      y     AWA f$   @$    ff$      H{   H$   f$   HT$PDD$ HǄ$       HǄ$      HǄ$       H$   HD$`0   HD$h迥AH|$PH$ADD$ H@H|$+$   H$   I9tPDfAGA fW
AWfWAWfGfW(  AWAGHIwwE	  D$    HM HT$`@ AÇ;A       fH   fDcBE1D  Pp    sH  HE1HHAHCK D{BH@hIwHH|HKDO?IǠ    H HHtHPH9tDS@fD9R@rH9|uNEH  fF;D{rEtAfEH  HRHtBDtDGEH  AAE9sFDOIEHAfAgEHODLBHT@ SBH{HDHSH  TPLHe  @  HD$`    HD$hA@  HD$L|$pH  HGHL\$`M  HsDC CBHvhHPJ4LLH   D|$(L   If.     H6H   H9tC@f9F@rFDtN9LuBTFfB;TC   EuHFHD$0Ht@DtAA9sHcADQLPfuPHDHT$0HBHo    A   ED  H{LLLT$(
   A   L  EALT$(A  HCH  D)o      A@y  +  A$LEG
HT$`H<$IL   H9.  AOVAHE1/fD  H$L\$XH{HL$LLLT$(pH$   L\$0t$ H0Ht$8ՉAt$ IG1LD$XHAH93  A@
D$LLT$(v    H$DL$LT$hHC$Hx Hp|$LT$HDL$I  HD$8H$   DL$LT$H$   HCL$HxHL$   L$0  L$HcL$LT$DL$  HA     Ht$XLDL$L$rDL$L$HD$XIA$I$IxAE=  I|$OA     CD  It$H$   LqE1Ǆ$       1f$   L\$`MtFL\$`Ht$pLT$8LډL$0L\$(!L\$(L$0LT$8AQHD$p    H{ABH|$ LHs(LT$({A H{LT$(     HKABo  IDo  Po  X Hs(H{L֌AHF|$( PD  ƀ  8PD1fH  H  @@   H  o  HWH  o    o  HPH  ODt$ H{AE1L$   Lt$8LT$ H$   LI~L|$poLT$ HD$xAF
R  Hs(I$FIT  HBfAFAr   HT$`fEF
Ar   L|$8EZ1fAWH$   AAOfA+Of9v1|$ HrHDH|$PAE1H{Ht$(IAfAO
LHHDHDt$ E1TpLH$   E1ID$`AWL$   L$(HI)I4LnAWLD$PIwIxLD$ HnHAGLD$ L$(HITP    fHH9ulL\$0uH$@H{LLDL$(LT$ ߎ   LD$XD$L    LT$ DL$(A@
OA   HuHU H|$0m1H蘌qAAR   JT:HHT$`It$D$mD$HCH|1AA   lI$DL$LT$HL$HI< H)HD$XHLmDL$LT$   L$HC  Hc  H5O\  Hx ?  @ AWAVAUATUSH(dH%(   HD$1HG@|    HA   GD=  GBGH  HDH@9     =  HAą   CBDCH  LlHAE
 t  GteMAF7  H{   fuAFIDHGH   Aą   AFH{H   u-gDf   1QAą  AF   @ f  AFo  ID o  Ho  P HC(Hh f     HD$dH3%(     H(D[]A\A]A^A_f.     11'Aąf.     %   EA䵇A
     1ƃ    CBDCH  LlHHC(Hߋk 0蘉HCLC(H@hIh HHu   f     H H   HCDtHPJDpD!΃tH9t{@f9z@r{BL9lHuH<zH  fD9;  v
fH  HRHtBDtAMH  9wALuLqf]qHL1HJHK HAą   f{@ ZCBSDL|HHCH@hAOH,Hu8  fD  C@fA9E@r9sBE1A   M;|HtqHm HtPEtKItLmEDA#EDuE1A   f     Af.     HCH| SDEE@ HƠ   ADuf;Dsw9  HC(@   AUBIDHAUH  DDPIA@   I}GD  SDA@ID HGHD  Hs(HV HH+  HV gDAFH{HT$1ItAąHT$Hs(H{iAą3f     JDA@_HRbDRfSDo        LL$L$=A  ASD7A,SBHSH  MtU AvLVDHTDJJEȉA)D)EB
 G  Au}AIM fDJH
1HfNfDAuLH)HgAUANHct#    ATEf9rfATEHufAmCBH{HcSH  H   HADELpHD0s HGHHCH@hHHuf.     H HH9t{@f9x@r@DtL;luHpHtFDtA}DDHA9sC|ELDGAfAuDGJ|H~HAL:AtH@ LBDfALCHu   LIu(L$pIEL$HDSD2AMDE1ɋSD"dfD  AWAVAUATUSH  dH%(   H$  1H  IHHtAǅv  A]|     Im \$F  H]  Iu(H}(  Aǅ4  I}(  IEI}h   HEAE|E|AuxrAExH}XIuXH@HdAExIUpExHEpIUpHEpRPA}x   v$ HMpI}pH
7A9UxwH}@LeHI]HH   LEE   HHEAƅt\DA   fD  DHH4HHHH9v@ PHHHH9rH9u
H   AAE9sACA9r fHuAKHI˃A9sDHIU@HtoH: tiA   H\$   LE    H¨u/HHHI!  H;wHHHL96  IU@AD$IH;vIH\$M4$H}  I$    D  DDHDt$HI4EDD$H3!  EDD$L$xtRtND HH4HIH9s    BHHIH9wH9uAtuH  DD$DHHl$L4HtBLHH)Hf     LE AHLHI9s9AyD)    B7o DAHHALHL9wI9  oM A~HIC4H9uDD$Hl$9
  DI}HI$_A   Iu@   Ht1H}@ h  H}@O  AǅtM|I}@  H}@  HE0H  D  HH@0HuH0IE0I   HAE8E8HE      L6_@ 1   LE1oH$  dH3%(   &  Hĸ  D[]A\A]A^A_@ AHtM|L虊    IE A   HD$(L9h`uAuxI}h1nIEHH8 uAE|gA}x  H$   1ɺ   LHǄ$   0   HƜA}xMe vyA   H$   D  IUpDtOI$   IM`494  H4@IEX   HHHHIuPH$     Me AE9uxwA$   11LHD$`    H߉D$0I$         1HAǅt=I$      HcD$0AD$  HHD$    HD$    HDHHD$`1HD$PFIHHT$@HD$     D$L   HD$X    HD$ I9$     IE(L98   M  IUH$   HD$p   L8HT$xLt$p   HLHJ   H$   jk  Iu(HL9  ID  A   ] A+   Af     HxL$P\L$A    I$   1HtH2IcE8HHHt$H9    |$L&  H|$D$L    HcL$0H)Ht$H+D$H9m  Ht$`H^  1HHIH|$XH)IHD$HD$PH$   Lt$pH߹   HLHD$p   HD$xHD$H   H$   *+  HD$Ht$@H$   H9H    Ht$Ht$D  H    HxH    HyfLt$p1HL莚   HD$xH HD$ HD$`I;$     1H   HD$    HD$    HHt$8  H$   Ht$8H$   \iH|$H)|$Ht$H)H    HHHD$HcL$0Ht$H9~OH)t$VHu@AN1	   H`t=uIE(Me H$   HT$`HkHHT$`Im0HRAu8I}(MuH  AǅtY@ Hu L  AHE IMI9  E
   }tzHuYIG    Hm0H   IU(HHHHM HAE~tI6H,         BHH9  HI;uAIMI$   HE I$   uHU0DH~HT$D$XH3HT$D$H9s$H։HHHo;3H3H9rHH3)AćI~ I      u;D  PHHHI|6 t!H9vI    IE0    AE8    H9wߍxH9w0oHAIHHLHz uH9vIXHD$IIm0H   t	I$   L$  AǅM$   L$T$IGH)M4HM Hm0BHIHuILl  LL  IIE0    AE8    HD$H|$ |  H\$(H     I}(Hǃ         1L_Aǅ"1H}Aǅ
MMMu I]LAvLH҃H{HAHIDITHJIUXI9NpICNpA         o"HH`ojh(or p8oz0xHoZ@XXobPHxxL   `hEuG   A^EHSHI+N8A!AHcAvH)DHV  IF@   HIUHP0o*HXxH$   H   I+F8$   orL`H$  $   oz H\$$   oZ0$   ob@$   ojPH$  L$  $   E   AH$   UD8Au%Lx   HWxxA   HD$A>Lx   HH$  H$  H$  uWAN   E   A^oHD$H$   Ht$pHHT$0I,Ht$ )AǅHt$ HT$0Lt$hLd$Ll$Lt$ IIIp@   LLLH    H)LE H$   H] LD$0LD$0ALE 	  H)\$      LLLAǅ   HD$xHH$   HHL$hHX   HD$H;      HD$ H|$HD$xH9CH   LL@   H)H$   Ll$LeHmL$   I<$L)I,$AǅtIwSD8[Ll$  H?L  H5E  I} '  Ll$Ll$*I} $  HL  H5xD  '  I} '  HK  H5*D  '  I} 
  HSL  H5D  '  I} S  HK  H5D  {'  ff.     AWAVIAUEATIUHSHH  dH%(   H$  1L|$ H$  D$    L蜐M   Ao$   Ld$)D$LD$LLL諕t'H$  dH3%(   uZHĸ  []A\A]A^A_fHChL$d@DLHHHT$ L8HShHL$ HfD  A    |RD  H   AVAUATUSHH   A   9wx   HHWpAB2   W|      	tlKvHHGX@fHHHx  ZSIHt_H  HDHMHChHtJHIU L(AMD@Lm 1[]A\A]A^f[   ]A\A]A^f   øظ   ff.     IHtXHHtPV A   A;PxsGIHpt;FD@u5Ixh u.A@|u+HHNL衎E1HDfD  A   DAff.      H   H   HOH   HG@|   WDtkf@ tjDGBBGH  NDHtEHAAD9sAWDHAD@AD tADtH  H1fH   1fD     øøø     HtH t GD@t8HGH@hHt+W HHHu@ HH HtH9uHHNff.     fHtHGfD  1ff.     fG ff.     HtKHtF9wxvALGpA t4DG|A  u7H@HHGX@    HDE1fD     f.     A   A%
f.     AVAUATUHSH  dH%(   H$  1HHusHtnH   9wxv9HWpAB*t+Au"G|  tH%   %
fD  H$  dH3<%(   uzHĠ  []A\A]A^D     ѐLt$IHH$  LDD$΋HChHLDD$JHDHT$LL0HShHL$JsNNff.      AWAVAUATUSH  T$HL$dH%(   H$  1      IG|  HPIH  H@   LMANxIǃ   IFPE1   HX`L9   H09tHHuEDDH09uE   IFX@4   D$          H$  dH3<%(   I  HĨ  []A\A]A^A_    HsLL$NL$\H|$/f.     IF 9H$  IFXE1@4g1ɺ   LL|$0H$   D$,    HLl$8HT$@Ht$0HLD$,   HT$H4$H4$HT$   $   H   T  TPDfLNHH     EEuEFxDIVPHIHHHZL:HB     IVp@4
IV IFXH   H4>WIv`HT$Ho
oRPoZ DX HD$IvXI~PD X1EAAFx7    =%D$   un fD  A   IvXA  tF4A	fD9t
fDn4AN|   X1f.     IvX   W#
   AF~LHT$H4$\MH4$HT$HH   HD$PfI틌$   HD$HD$)D$PfD$TH$   HD$@0   H@h)D$`HD$p    HD$xL$   tH$   L$  Ǆ$T     I    HL$IE M(L$IU $It3HH$   I   vS9w$vNHvHH   L@Mt4H@    1H     H   fpH   LǃmHD         Ht.9wxv)HOp1tHvHHGX@%  1     AUATUSH(dH%(   HD$1}   HHtu   9wxvIAHWpAB*t8
   G~u-HG HW`H   BB9  HT$t2fHL$dH3%(     H([]A\A]Ð   f     H|$HG(pȕHShJHt bDHHuuTvAueHSp1L
KTm HHSXfJHB    HB    HB    HB     HB(K|H|$D$D$-D  HD$1A   H߾   HP0tK|뼸ćHSpD$B*H{ D$G    Ht&9wxv!HOp1tHvHHGPHP1fff.     @    Ht&9wxv!HOp1tHvHHGPHP1fff.     @    Ht&9wxv!HOp1tHvHHGPHP 1fff.     @    Ht&9wxv!HOp1tHvHHGPHP(1ff.     D  UHcSHHHHxH@HtHGHtH(HH1H[]ø   ff.     HЅtFE1fv9A)к   tALIH94sۉкu1ADA   f     SHcߍ{HcHFHtHL@H@    L[E1ff.     @ HtHrDfff.     @ SHH?H w[D  H  FHtH  HH[D  ATE1USHH?7H;Gw	D[]A\ÐH  @0HRFHtUHHPHD[]A\A   ff.     @ UHSHHHH;BsHHH,1H[]     HA   EuHHff.      ATUHSHH6HH0H;Sr IA   Eu*I$Hu HH    H|HuEHE H1[]A\fAUATAULSHHHL L;`wIL t1JuHCHf.     HHHHHQH9u1H[]A\A]@ I A   EuIE D  HLHM	HMt<L INDI9vfHHHTHI9wIHNMuLfD  AWI   A   AVLwAUE1ATUSH(  /dH%(   H$  1)   D9|MMcO@ MLω~(HcIDfHH@  HHHL9rLI9uEc  AEIcAHlt)D~.HIHcH   H:IHH\$H
ITHcIH;LHI9sHLLH;H9sH\$HH9H;HH9sH\$H:HHDNMc    KEH9w-HcID@ IHAHH9rD9|(KIILIL9HD$)AHAMAD)I89Hc|MclDFdARMcDTE|$BtAD5H$  dH3%(   uH(  []A\A]A^A_@HЅtJE1fs=E   )ȅt!AT	IHH94v׉Ⱥu1ADA   D  UHSHHH6   HE H9vwH=    HHE 9sEpIHIAHA)JT NDHLHI)HHo1BL9uoH1L= H[]@ HH3HH9t tٸff.     fHH= wHHoH1      AVAUIATIUS_   H2@H  H     HfAo<$   fAot$fAol$ fE
   fAod$0fAo\$@HD }fAoT$PfAoL$`u fAoD$pI$   m0D$e@LH   ]PU`Mp   H    fH
H   xp h0`@XPP`Hp   A} 1LH@u)=D0AtH[=[D]A\A]A^    x9A       DEA   d=D0ff.     @ ATUHSDgHHwpDA   t"DZ>   DHsp   	@    HE1ɹ   =HC8HHtVA   u-Ht
   H9uCHH{HH1H{P[]A\D  Hsp   ?H{8Hu    HC8    <[] A\@ ATIUS @@ HB    "= @@ uLc1[]A\D  
HcM>HCHHtC   LR<[1]A\ø   @ AVAAUIATMUSFH~   D1 >ÃtU  tA$1[]A\A]A^fD  AEA9Er1    <t΀@   ߉1;fD  {; A$[]A\A]A^@ AE1HF  HPHe  H4HcHf;H{?ff.     fG   ATUSHH   HtRS$B~BHH,@HcH)HL$@II`f     H|/H0:H   L9uq:H{Xh:H   \:H   P:H{0G:H   ;:H{h2:H   C   H{8Ht	Hsp<{   ;   H{@ tM:KH{@x) HcHH   9u
ǂ       uڋCpHH<{uc[]A\ 3;c[]A\    ;H{@ tfD  ;;UfD     <H{8H ff.     @ AWAVIAUATUSH   dH%(   H$   1HD$ HHHD$:
   H<11H8tA   IFE1HH$}<D  A         IcII,D   LmhE~4A   u)A   IcL8   u~A   E   D   Et%Lmxǃ       ED   EufD  ǃ       I~8AA   9A   IH4$I~88(HcA)IHf7D8A tBEh\@ H<$9H$   dH3%(   u(Hĸ   1[]A\A]A^A_H|$Ht$:g8    AUATLgUSHLLk8H;   L8   tf.     LL7   uL!93         HcǄ       H[]A\A]fD  AW    AVAUATUSHH(L@HT$Eg8IoHDA|$HHD$8H       IID$    E.  E1fD  DHLh  9k(   EE  DE1fD     A)ЅtB|A+Hy؉Ѕu1ARA9d  DA)L    KtKN    L)AI)f.     BHH9uL)I(   HCu=HD$H   H/9tiHt$H   uE1H|$k7 AE91LD$
5H\$D$HtL$H([]A\A]A^A_f.        HaCuE9sDD  HLp9uD$@    D9rH|$ [AE9CcfD  A   IFE9r6I   Rff.     ATAUH   tHD]A\ HW@H1HBH9@tjHGHHOPL   L   M9HBH` H   HB0t;O   1HG`    tIAH5HD]A\     1AąuHj4AąuHD]A\HP4ff.      AVLGAUI͉ѺF  ATUSHH@dH%(   HD$81^t:Aă  HD$8dH3%(     H@D[]A\A]A^f.     C &  fLt$)D$)D$ D$   HD$    HD$        2Hŋ %  {1L   +3uAE    {1    4H6  SDCrHHH9}AM   HH@HCE11      K3H   AU HC@   8  x    #2D AD$t	EE1D  H   H5>M4AąK   fD  ChE1`fD  1ft$    De Au6{1L   1uAE      k1D  ED  fH@(    Hl$4@H@HS@HB`    B@BP;2Aą   HC4Aąt7H1    DHt$2cDCHt$V   H1AąuHC@HHx!4AąuHC@HHx@
4HAO1EH  HC@H@0    H@8    AA1fD  AWAVAUATUSHH(  o?dH%(   H$  1IL$   L2H<$S  #  A   E1;Icͺ   L2=     $     $     $   p  E   H$   H$   H9   D$AAM  Ht$xHSpCHN1Hu	HT$HSpHH9vHCpHHT$    1Hu4KA   HCp   1HH   1H$  dH34%(   J  H(  []A\A]A^A_f.     H$   fo$   fo$   fo$   fo$   )L$fo$   fo$   )$fo$   fo$  H$   D$)T$ )\$0)d$@A)l$P)t$`)|$pAA   +D     Ht$HHC8LHHD$fL.$  <2<$  2.6.H$    $  2.6.  K   fD  <31H$  
   /h  u1H$  
   .~?fLHe5     Ht$HfD  fD  A	ty, K  CHt$      H   =   F1H   H   HD$x   SH$SD$HD$@fT$HSpHD$pHD$   Hf.     CfD  f$  32mx.c1H$  
   -;R@ f$  34>x.41H$  
   b-1H$  
   @-M,D$@ ATAL  H
  UHH  dH%(   H$  1IR  VL   .H   ZYHtLHHsZ  L   H  H81.*ff.     fHt    Ht	   Ht   Ho      U   H   SH(,HtHH@~   H      HC HC*   C(-H] C1H[]ø   @ ATUHSHH8HtxLc`A   M   HCHHSPH   H   H9HBHuHhH@xSHspHHH9HB,HkpCtLc8LH\AuCHkpE1t1HHH   [D]A\ff.      H8    u1w$ff.     H8 ut
w1       fHtHtG1fD     fAWA   AVAUATUSHxdH%(   HD$h1?D$,3  % D$"  _IHl$0ILA	H*Aǅ       
    AEL+E}$0   IE0LHD$ *   LI   I)   LI   HD$)HT$MLD$I   H	M  H  H,IFAA  B   MDH%   LD$B   ED$Aǅ   A     LgAǅ     
 @  L$,  T$   A]$Au   (k=IEXň   H  Hc   (H   H   Lh HRHpXH@|   HIEhHHhHHHH`HPpI   HPP"  D$,A    LD$4tH|$8n&fD  HD$hdH3%(   {  HxD[]A\A]A^A_f AsA    I   Ht8      'E}I   HD  A   eD  E}fHL$,DHLmAǅ#5D  HL$,DHLEAǅ;
D  IUPIEHfH\$@)D$@H   H   )D$PHD$H    HD$P   H9HBIU@H   HB0D  s% A}1Hھ   %uD$,    @ MED HLAQ%@ HtCUHH   Ht HH   $H   HuHH]$@     AW1   AVAUATE1UHSH(  Ht$L$   H6T$HLdH%(   H$  1HHt-   H$   f$   H}H$   <Aąt4H$  dH3%(     H(  D[]A\A]A^A_        1Lq\AąuHE $   PAT$%HD$(HHr  f$    T  T$E1D  KtHH+HE K\HI@HH$   D9wD$   D   fE1  $   H   HHD$XHD$ H$   HD$@HD$`V
HD$fD  FHt$X    uL$H   McJc   = ~'   Ha  Lc   Jc   MJDhHt$XIHE LP*H      $   HAH   HE I@B   f  H HH   D  DBHЉ8fH$   f   H|$(!fD  H   L   WfL   9Lt$ DVH$   1HpP H HH	LH	C:   $   Ht$X1$   f$   fD  V
f$   uWH   f>,f$   ff$   H   V
f.     HU H   R($   Ht$XD  fA     Dd$LE1IHD$  H9t-$   HH   I$P|(BLsH\$XHAI$   HD1H0HHT$H$   8kIcIc   = ~(   LDIc$   Ic   IM<Ht$`IGhHI$HϋP!I$   H0HL$`QHHI4I$   I$R     IFL9t$@  Ht$XIDLFHAtH9t-$   HH   I$PQ'BLsH\$XHAHt$@LILLL$8oDHL$0)D$`oL)L$poT(E$   )$   QNHL$0LL$8Afo\$`E$   \fod$pAdfo$   Al D  LHʉ      IWx E$    HD$HF LDd$Lk H\$(9A   
ff.      AW   A1AVAUATUSHH  dH%(   H$  1H|$`Hl$pHD$     HHq!Aƅt2H$  dH3%(     HĨ  D[]A\A]A^A_fD  L$   1LAƅ   sH|$8     AƅuiHL$8    1Ld$`HH$   H|$(1HHH\$`H   D$   H$   LHǄ$      Aƅt)H$   L@ H	 1HL$    HDth$     LDH|$(1H|$ A+HH$   ^LFHED$       H$   C1 HH     H   fA
H   HASHCpDCHAPHǁ      fQ,HSHHA LHRDA(L$   Hǁ   HQoA   MfAP
A@oI I    AH oQ0AP0oY@AX@oaPA`Poi`Ah`oqpAppo   Ht$ A   H   I   HVXLrXLt$0I  H$  11E1HHD$WYHD$PHD$HD$@HD$	HD$XL0HT$Ht$   H|$Ft=Ht$ HVXHFoB0HH+BH+BH+BAGXoJ@L)H|$0I   IAOhoRPAWxI   Ct[IǇ      Ht$h1Ht$0L牄$   L;t$0yR4fAP\ftAW\@ AWAVAUAATUHSH   dH%(   H$   1t9AH$   dH3%(   T  H   D[]A\A]A^A_D  HL$   1HD$    @AąuLu@M   H|$   *HE@Lp@LtLHc  H|$,Å^  E HH$H]8  L<$LHDHJ     M   LA   H|$sDfD  M	HH$H]8uH$    HD$u HT$    L$LpL$   HD$PLI9IFHA   @H+,$tH   @LHDHFH   tHH)uQfD  A   @D  HI)MtGLML    1 tA    LAM
     MtLT$T$tAD H$    gif     1If     AVAUAATUHHH8udH%(   HD$(1Lt$D$  @ LAąt'HD$(dH3%(      H8D]A\A]A^@ LD$  LH  AċD$u;Eut$HD|$A+yEuD      H|$Voff.     @ 1	f        uGt	1w@ !1wfD  HtHtG%@1f        f.     HtH   1Ð   f.     HtH    1ff.     fHtH   1Ð   f.     HtHtHG0H1@    fHtHt1       fHt[HtVHWPHGHL   H   I9HBWPNVHPPHVHPXHVHP`H@hHVHF 1f.        f.     HtcHt^HWPHGHL   H   I9HBHPHHPxH   HVHW@HFHGpHFGF 1HtB8F$1D     fATUSH  dH%(   H$  1   HtoHHtg9wxvbHHWpAB"tNG|   uhHS KdHHCXRU PUHPHUHPHUHPH@ HUHE 1H$  dH3%(   u4HĐ  []A\f.     H$  HHQ끸ff.     f  f.     AWAVAUATUSHXdH%(   HD$H1H   HH   HG@IH   P8   L   A   HHL   1AWt`IH5a  MOHH
_  EG@   HHDH   P1XZEtLH=M  Ӆx)LHӅxE1I@M9uEtLH=>  H\$HdH3%(   u+HX[]A\A]A^A_    HH=  ̸>ff.      HHt(Ht    H@ t1?    1D       HH                                                                                                                                                                                                                                                                                                                                                                                                                               2.6.32. 2.6.34. mdb.c %s
 x > 1 indx < numkeys rc == 0 LMDB 0.9.24: (July 24, 2019) Successful return: 0 mp->mp_pgno != pgno dl[0].mid < MDB_IDL_UM_MAX i > 0 i < NUMKEYS(mp) root > 1 mx != NULL IS_LEAF(mp) IS_OVERFLOW(omp) mp->mp_upper >= mp->mp_lower key && data csrc->mc_snum > 1 cdst->mc_snum > 1 NUMKEYS(mc->mc_pg[ptop]) > 1 !((size_t)srcnode & 1) rc == MDB_SUCCESS rc2 == 0 i == x dl[x].mid == mp->mp_pgno pglast <= env->me_pglast x <= dl[0].mid %10d %zx -
 %10d %zx %zu
 (no reader locks)
     pid     thread     txnid
 (no active readers)
 /data.mdb /lock.mdb -lock    %.100s:%d: Assertion '%.200s' failed in %.40s() IS_BRANCH(mc->mc_pg[mc->mc_top])        !mc->mc_dbi || NUMKEYS(mp) > 1  IS_LEAF(mc->mc_pg[mc->mc_top])  ofs >= mp->mp_lower + sizeof(indx_t)    len >= 0 && id <= env->me_pglast        MDB_KEYEXIST: Key/data pair already exists      MDB_NOTFOUND: No matching key/data pair found   MDB_PAGE_NOTFOUND: Requested page not found     MDB_CORRUPTED: Located page was wrong type      MDB_PANIC: Update of meta page failed or environment had fatal error    MDB_VERSION_MISMATCH: Database environment version mismatch     MDB_INVALID: File is not an LMDB file   MDB_MAP_FULL: Environment mapsize limit reached MDB_DBS_FULL: Environment maxdbs limit reached  MDB_READERS_FULL: Environment maxreaders limit reached  MDB_TLS_FULL: Thread-local storage keys full - too many environments open       MDB_TXN_FULL: Transaction has too many dirty pages - transaction too big        MDB_CURSOR_FULL: Internal error - cursor stack limit reached    MDB_PAGE_FULL: Internal error - page has no more space  MDB_MAP_RESIZED: Database contents grew beyond environment mapsize      MDB_INCOMPATIBLE: Operation and DB incompatible, or DB flags changed    MDB_BAD_RSLOT: Invalid reuse of reader locktable slot   MDB_BAD_TXN: Transaction must abort, has a child, or is invalid MDB_BAD_VALSIZE: Unsupported size of key/DB name/data, or wrong DUPFIXED size   MDB_BAD_DBI: The specified DBI handle was closed/changed unexpectedly           5	5 5 556646666666454545^5    mdb_page_merge  mdb_node_move   mdb_rebalance   mdb_drop0       mdb_node_add    mdb_node_del    mdb_ovpage_free mdb_cursor_put  mdb_cursor_last mdb_cursor_prev mdb_cursor_set  mdb_cursor_sibling              mdb_cursor_next mdb_cursor_first                mdb_freelist_save               mdb_page_search_root    mdb_page_dirty  mdb_page_touch          mdb_page_search mdb_cursor_init mdb_txn_commit  ;$     P@  `
h  0  P  p               @  p    8	  @	  0	  0\
   
    
  !8  @"\  $   'P  (  )  *
  `,P
  ,d
  ,x
   -
  -
  -
  1<  1P   2d   2x  P2  6  p;  ?T  A  B  DD  E\  PG   J<  P  P  @R   T  X  Y  Z8  ^   p  q4   x      `p    г  дX  е  P    p        4  @  \   p  @    0  p      @         @(  `    p     `  X  l    P  P   @  x    P   \     `     p  @  <
     p  0  P   p  (  x    `  px     0     0(  `<  P  d  x      0    (     $  P             zR x  $         FJw ?;*3$"       D                 \             p                2             X       H      8j   BEB B(A0A8G
8D0A(B BBBB0      \	s    AAF0^
DCKiFG <   ,  Q   BBE D(A0
(D BBBH  L   l  h	   BBB B(A0A8G	
8A0A(B BBBH   $     #    AAG WAA 4     @    BAD 
ABFnAD  4     l    BDC f
ABFg
CBAL   T      BEE D(C0w
(A BBBGD
(A BBBE @        LAA C
ABDM
ABHP   L     <   BBE B(A0A8G
8C0A(B BBBA   4   8      BBE C(N0i(A ABB   p  TD    Ax
G     +           z       8     
    BED C(D`g
(A ABBA H     e   BGB B(A0A8G`
8A0A(B BBBK@   <      BDD L
DBDq
DBIa
DBA @     Tj   BFL A(A0Gp}
0D(A BBBK  L        BBB B(A0A8Jg
8A0A(B BBBK   \     P    BBB A(D0l
(D BBBG[
(A BBBFZ
(A BBBG@   t      KED C(D0
(A ABBCE  |     L
   BBE F(D0D8DP
8A0A(B BBBH
8D0A(B BBBL
8D0A(B BBBK  H   8     BBB B(A0D8DPs
8D0A(B BBBGH     p    BBB B(D0A8G`
8A0A(B BBBA @     $   BKE A(A0FPm
0A(A BBBA      w    AG }
AJ  t   8  K   PBE B(A0A8D`8A0A(B BBBHH`c
8A0A(B BBBA ,     d    BRJWFUA H        BBB B(D0A8D`
8A0A(B BBBF  4   ,  S   AAD 
AAKn
AAH     d      AG0Q
AF `     \v   BBB E(D0A8G`Q
8A0A(B BBBFI
8C0A(B BBBA(     x   AAD0
AAD   	  )          ,	  0          @	  $          T	  0D          h	  l    Xm
KyO   	  %       x   	      BHB B(A0A8D`
8A0A(B BBBDg
8C0A(B BBBEv
8F0A(E BBBH   
  |#          ,
  #          @
  #          T
  #)    FZ  (   p
  dl    AND O
AAA (   
      BAD DB     
  <          
  H          
  T       L     `   BHB B(A0A8Dl
8D0A(B BBBC      T  I    Fy  (   p  "N   BAD0
ABA L     &   BEE B(D0A8G.
8A0A(B BBBF   @     X+   BBB A(A0G`
0A(A BBBD @   0  .   BBE A(C0NP
0A(A BBBJ    t  01    AI 
AA H     r   BGB B(D0D8G~
8D0A(B BBBI8     1   BBB D(G
(A BBBD    
  t3+     \   8
  4`   BBD D(G0
(A ABBG[
(A ABBGU
(C ABBC |   
  5   BBE E(D0D8D@
8A0A(B BBBJ
8C0A(B BBBJD
8J0A(B BBBI   L     7
   BBB B(A0A8D:
8A0A(B BBBF   0   h  |=    BBA J
 ABBA\     >m   BBD D(G0
(A ABBI[
(A ABBG]
(C ABBC `     ?   BBE B(D0D8G@
8A0A(B BBBB
8C0A(B BBBHH   `  DA   BJB B(A0E8G
8A0A(B BBBF(     D   AAJr
AAH8     E    BED F(G@l
(A ABBF H     `F   BBB E(D0A8Dp"
8A0A(B BBBHL   `  4J`   BBB B(A0A8J
8A0A(B BBBE   \     D[Z   BBB D(A0
(C BBBDR
(C BBBEe(D HHD  L     D\s   BBB B(A0A8J*
8A0A(B BBBH   L   `  tb   BBB B(A0A8J

8D0A(B BBBB   H        BLB B(A0A8JV
8D0A(B BBBGL     r<   BBB B(A0A8G
8D0A(B BBBG   H   L  Z   BBB B(A0A8D`
8D0A(B BBBKL        BBB B(A0A8G
8D0A(B BBBE   H         BBE E(D0F8L
8A0A(B BBBC\   4  p    KBB A(A0
(A BBBCA(F BBBCF0      r    CS     x            $S            p            |            xv       @        BBB A(D0G
0A(A BBBFH   T     BBB E(A0D8G~
8D0A(B BBBF      T       8     P    BBE A(J`M
(D BBBE                   *            &          ,  8          @  D          T  P          h  \          |  h            tf            n       H     \_   BBB B(A0A8G
8A0A(B BBBH0         BAA G
 AABK   8  <Y          L  9       8   `     BBA A(DP
(A ABBB      (1            T1            1            1                   \      2   BBB B(A0A8DFHAR
8A0A(B BBBH      `  6       (   t  PD    ADG n
AAA       tW            1    Aj
A                 ;    AQ
Fb 4     a    BDA T
ABBu
ABA(   <  HR    ADD ]
AAH  (   h  |^    BAD SAB  8         BBD D(G0J
(A ABBE      Z       L     P0   BPF E(A0A8G
8A0A(B BBBA      4  0[       (   H  |    ADG 
AAE    t   .                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           4      4      #"     !     -"     7"     (#     X#     #     #     #     0$     p$     $     $     $     0%     %     %     &     H&     &     &     '     P'     '            V             f             p                             0      
       X            Z                          Z                   o    `                                
                                  ]                                        @             @                    	                     
       o           o          o           o          o                                                                                           [                     60      F0      V0      f0      v0      0      0      0      0      0      0      0      0      1      1      &1      61      F1      V1      f1      v1      1      1      1      1      1      1      1      1      2      2      &2      62      F2      V2      f2      v2      2      2      2      2      2      2      2      2      3      3      &3      63      F3      V3      f3      v3      3      3      3      3      3      3      3      3      4      4      &4                                                               `     bfa4cbaae8f93980107fe5254090f6b8602d33.debug    ~ .shstrtab .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt.got .text text_env .fini .rodata .eh_frame_hdr .eh_frame .init_array .fini_array .data.rel.ro .dynamic .data .bss .gnu_debuglink                                                                              8      8      $                                 o       `      `      p                            (                         
                          0                                                      8   o                                              E   o                                               T             @      @                                  ^      B       @      @                                 h              0       0                                    c              0       0                                  n             04      04                                   w             @4      @4      ~                             }                         ,                                          X     X     	                                                         	                                          )     )     $                                          -     -                                               Z     J                                               Z     J                                               Z     J                                                 [     K                                r             ]     M     @                                          `      P                                                `     P                                                         P     4                                                    <P                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        [ksH_Ǝ	Uf.&qW~!RR
T%$Zt=73%~k';
R>nǹd>l_lVΓL_,sqzjeYZ<iⰜ!D[~y4.c'jYY.epKB4,cyDg(O>w6Et*HRth\$xPQ̄(id܊DBqQfDH
KG`6CYƟ0~`A$
`\x쐨c<ꡭ$f-VTGJZgL|"Lx*ZP'-#6HF02c\<@M,X@82ڏpDSRJ>EYݜ'I0()~":|p6pP5+qJ{fѹHl>Dgj>gszyǉ i7^y(8<0[,K$t	8hK_|?;Ks?[R)}ޝOC0
}OYĦ%/,}Ud<WP_ n-y<U"_"Bmbջީooȳ_pytg,,,o[l85'ّt vgeoF͑
?1f`S&Q_ҀWelg^]ǀS1p1(5U$cD9'K	[4lGCjؓA=lө @5	3Ųd鏦H~تnL"e"I*hNQ^8؋k J:?d=	;SQA?G!zGlՑɦ^$|}r,br4KE޿DRgwū
5ߓUY\ *d#[v"*ιaIE^[!dNn 2B!x-zM"ģ_'$U$Bd>F\8b+E|Je#z<;Vi دG /$d˂`4kVqVY~eu2$8eg9/Ӌorۦ×}w_4Z*3,[15#V0'|^#|ZNk(8];TӨr(CqHӉI1ON޽;1ѵK:ܯI\4a/pE3;I2|7ʨ_dP$z2
=oüDo[	,MuxH/)Q}@DD|eQ#,΃y҄Qy¬H	_Y$]&	y m"6/ֺusa>yTa)=LBDOR
>,{fb%B  v!c9J,
9TGg<p:q4*LϳLw 9-7hBPYOPig#6ADxf*Or7mNu	YNw@PdsP^BiAkep=q(N7aYmj[}v`wc V%F-[P5qG$G#i=4mY)%@
Hg)a<QKֲLlU=F 4:PwV9kK<h
y7A":i:g 1OXFGloےSs1/օZ	%EB|`s0F/lPYTf$"')
2(ڶ^
8 e4g_DQ:>sÑl
p2ta:ǆ}Xځah9zAv軖EW-M}n9jϧvrb	v!<öv<׍D״cY#^?$pײv?ʒt}xfj7at$@*N(  4f
]IQቃ4U0J>rEy8	夸^D0@sxPhz
.0S_C0h%u*DX0Ut^4]*CXVXl+feyoWH>5FPΩ &Θ̊l.^X2`.b(qRK,錂mq ۫u[:M?K(=I@iLj>B
):C!	q8aʺ6DNs
AMS=:KvҠD?*L`$ia˪189^* T0<6uAptm͜sP? Ha>s֕mVkJKp}3fһGw곪@W:aij}8P]VmN(ɒJ5ِ7:ΨWM_b4$rTDDIh
$u mАvx܀ƢLk?nFIE	/q>GiT-rm)Ix]7k<O<ժ}	5 V2BIhƟ#Rz}H'IXa(Iϗ@Q LPV
jn%b(Qf('e]{ZHa*CPk
,(F1j:#WP'ZH
Cf"X Xɀ)080Xi]zO2G#sEE\HzE0	}UO',.@4[{Uo뗭|xvs}>|F
k/XNi/e+؏ˆpntն@)?![%5WIwjRpѦ5EB}rJGFyB{t<%Nd|=:e;G.sRg3G clǌG+ϥ|@_so%;E"UaPʄMB$QC cѬ	|r:ۛOzHAXS.@{o5"r,>ogWlt=6%.{fF;SU&.g&yEhzӧj0 ~:ꮧ詞veTgS[wFJ'"ST\d9`^#QP#NEJ_PnXEX&>՘~s]Q	Qtut<܍Ga^Mw	6R&Gr%aՅ˓iПUS~!
/]bfmJ`&*6*u@/
|{搮ӪJGEUƪ>fp4v<WdA;XN~(*@:H Kn&Y]1?Y$V8ٗ{z^b(e'xO"4c86^+xOEᛖ3\#4"Y陾CZr\X^^vv7@n%e <47qv^k[q~٣N(8EX5{s5ON`qBܥ y#Fe._3~ˁ2-5d/{95ӥ,<7n0!(Uȵbn+K#Xcv]>)GS79꺴58bx)#Zt:ui
DԊ21=.꼏ŌS> ?kbx+$n+C
,tDEȩj^,
D||gom14|&ME9GrDyKl;L'ao`=~TH;&y4qm2-;v?]^B#}n׵:mx"Vu2k{='r-]s+腼oFڇ=\/gp5boC,Y/7շl	OW\}eHxh@DJC|[!k%ʈ;׀s_@ypzf70fk ɟC}$@*F!qńsDwO5|e}YCvJJ}q^n_UrM5B%ĨY!k_zF=i
6DvA/ˆ5ndo]/]Q_!-NtشUd/XAJK?W+~eylXǖ͜FzA?x?,=Je9 +aE[]:/A7l(at-'"np7߳Cշ=uF:~2-Sv^}7>۞lnBYKgT	Y)dIr~{sENuVݮ@¶UeK*a[v{vȂcN_&>{aw<&uĨR7I^U82lEO9(ҢUmz1yt=+]+k:anװ_uX?|(
!Bv"o :}W a{}ۄ2Fc5qXsN^.I+lv_Vv^J6e'x$Y uXb׽شap ZCzjϻs@t8!jˁw_UsO{=	/Xe{.{>oO2T6w ?reCbg:F'l0
>&"Q/3-{H=&o
>WݾΛZ,l-?t4
x7|zn` H1h9t?]'_NaO:.䊪xBTÏ/iYMi,ο?|=>{Ity9>NUn3V*$-TNO|JddQ|i
n߿Hk'="Ivxyte/kt)H*fu)=^k|;~&D2"7d8_	},Q|r
>zuw^_ޮc~_AbLNkK^I~i3HC~{HȮa@:uXR[!:SF8F4#~q0o<1ƬYt	D0QmyVY%Nĸm22IZƫDa7K";m?9`6F=XW@XO_I<P1-ۜszZY}Y_]?\߀D?wi"ͅr&Q	uZ`
r:ÄL߁7#Z<5y:M
FR6D@g^i D1_Y>BUJ8ۻ+x?Dp&:vD~ܑNGɄbp3G]/f]^̦f:⡿y^kV%(hU`KN<f SwǛ׷o:`}%
V-\3>OT/`fju#J{LQ{c͗|¸M su5 _Oa`"96?9T(l ~BdbÍPMl(rtt
m#.
nR/$F
:jC	y|wH]gu&eڦf /a|Qjs@7͢gMd3`l?/j F3_4Ԁ
BeTZ:!8^+
g(l3xK
TBG#`dgR---[[Z/gj>֤n|FzA[%ex̛8̂#T1*JXN)XK䭥`^,|酠$7K1sJY<!2f+ar-hủsȨ$bcxzR
`ɴg`@KS0}w<D5&q=Tn%@/K\58
lP,$L&yfjob_E2'ujF,C2]ÏSaw[(#³ -w=cBkxY(+C#,jLT&-	 s'/-@-AJ!:KC̕e.8L$OQ<1&ò⧠cd} FgFc0K
<MȜ+џ@hAN!zڄtIa	\! <CƈӍC$F'+'CLp8Åc#Σ(-K)6gr-Q(F(@|$sP.+19QEa-(%pk@|G4 {gid	uTI30gZB9iJ yYNRas`J)IqXS0A8*wu{fͬꙠvĮkV
>NE$Sp5ݤ%SSqJ}Ml`8D苬ż<'&;ӹ
6hGEÈRj=?%;;9F1SdҘLgXkCNF|y&Er%Y
=7
keRJHJ^J(@$eA(d`aVvXv!4Y&2Qْd0Pw5!bw3{!` >hf˚{_ ``	#<cNs9U&j6HN3.qhm1$SE#7!8BŲDC~SNDkSCڎX\H?/p4HFj1ŵlx5ѽ48 j`i3!h]ߐxF^RHmw(TQ{c
c@sUX{~$[1MجLs0,֕L@WGdKF)sgɈ
b
"\a-K~F!*123XF9WTg@L7#YYrf氮)uAnПbNd\lO#x~zqѢA@;ua`\A&mz[.9QAZ-8ށp+vZ_#Қ0Ml7ڛ0h() ϲCdLG3&	,QINjxSk,>$qΝ)#x [:VKs0fG`=ܸ%v+B|-Nא=`v|/5,=ONs3bfko┻V8h<!4"{2[ϡ?@ BD	vk<RUl6tTUnjvA]@~ǭVo%_a9I0R}͖0Q@t<fk-4J
S'u+|Zt'T$V;(I(d^MIn*>V4]nΑT_Dǟno.o"ePX[}~Y|*M[WC!Cn*`-{>{=DvuK;5bSҩWH7IU{G
bfOspWbZ%.&}#'wt5MwFIP5'D~Yf|^/V63=i8fvkRߚymz7שsTUâs>é #5נiHb̓~@B½{ծoI@:Z[?ͽ*"'<
aek~R)	0:\o/[/.߼Fhj`*kFWa;Y>GRijTUH@~%gڝXʚGrSl.WR5uzg</y6Wҗ0-BPVpe	`z+=6
)JEt誳QH!,m.iAŜdFCL
å,d\PUG(I!8؁W:]WC	2'hhwo>Բ35P3?:31tgBI~I5,/1ZlWxvD@B%u_\:ywEMY!}P}ZB|;y{{GUI('_AR*AOds`VX`qJ?jj0ty$nF]]GQ7}	[bٱ(5n n0Sj
&WP:91gb՛t1SF,ɽ&ÏIZ$/dbھp_lh)<@>50$p2*(* VR &sTP
"g%q`6 i<6P^mGΈaXA+<QX^By;
X90h$oa-{kqV]{[_kMih#ר[5?kSݑrZEYvu+}14l	԰ o
bj'	ޮbu}
Mcdd>5DLAԑxԟ
&~ی,;R{T΅/s`&gyli
Gq<)t:X+yiO$ɕSip
db6r'L~BFfX/%/	凥(ے"REb?2"BR[nCj'_LV蚊З7 nૃ줛1fb^)|[#V#Qٴc[Udw6h̧ÖewB[uHƚo6^2 c.ߴqdG)XO@jo#|hT B|*	֪M+MPi	=Qۖ <NrB4=^['9ԏuNcYXkno6q-6H3oQa}rn9zB
̀^~JEz2dv/o?+oɎ/ijTыllnsi(evDx<{-.TtW]
yMPQrgEwo{ +ʈ0KlmPF ~bX@*h?IمN0>,{Ll'g0y.Z*ZMn`mkAzqCa֫!-N]ֱ6	V;
M}^s_mUБ1wc~GFgNMSpkѴE6:ݦa}6}~k|EM/zJsFtFh*{~U]?GtuS+D>*н@ \GNfpˮ5}ϓ%H}ڝlCt?F}
|bfO}<zAOWM$YF
S$پA~kp? 3Sp-LI=4憊BȲp	^l2->j?WT28=1 4{8:
\b% 7Sl8%7;/[[ڻqM~f?'wutz9i!1*1(j9
5IGbϊ'pjN'{WeLFrQ>n _>BjeSsP:KkuڕcRMm[KP&[f_O.S!%.=󚁰kfNjh:o1SZ$ծwh
8}ciw}|h"zkAۧ,Q]&/\kz[M]᙮\`t~HbL^!Xɮo)k1hFǣ__߷zUOIw62'GPL-/[p:so"CעXq(s'_?ܟ!!4*,zG@vz¯vԾ:>0BQa.v(#m#`OͲ!5C3uu}朣[[
vv7fc{\,7osn@4G$R=l{o_kDs&ΙF*a2Qh%K1PZzRN{-S^	EU:8G)c1a\t]A2`ll7JLhm]eN-9*N [f~L$vs4mDT1]H]$j-dH1Hfވi"^)t=Oϱ9XB9SKTJ+p|Ahˌsxy2S+KƌS*W+=&'WHJ2´HCa;;ǌw1W᣶TZG$l+&Z2bxdf=|Ǩ4&nobj2U¨ܔd&_-ӫE7YuZSNOZ3`]aЅ?_Tkv"WKsCQS\[߄FT_jCAϖ[nh@jh&B-@Xa\nyQHt)JM<'R9yfDADT0AiKEpBsAh
TPq{
)%m釦p._ڮ~`бvm*v=3 
ئD-K8
uP$53-J yPj,$'?lf
|Xqq% .Iq^/b-DF{̯LlFYOQ:GJ\f7"\v+J)!vf}&1o/av(GB 4'(?X<p~.kߥ'{c5>kBG[i;4-&a'qoxKW2nn(xs#՚l|	bw2AnSsj Ԇս?)}u4;m2\-?!/(
!6wti^nEG]!(J&I}Ι\$OU]kp7
ǵ؄);6̋HRm4qbHDGk¦sR̨hWm^*xi[ Fl]J0D0aGo^Y4cjrvNS.Iwn^
}`~u$ę^JF-0Cӻ̤x UUgRԍt}Wπ&8Vu`Cvr'I'Vx2g"a̲ރ^~{f
/gL!%hT%N vyR Rʠ@ʦ䵂=a<kq؃P|4
DKD
ip&:ˍrD^,U~Mgiܳ$[Úv*jp;UG1e~ۏw|jЇWORzwd
-!|<|i<Phn6TA_S阻G'R>)PBAP03?2pcYe/bMc&9~Bv:-б(rlZ?.mVO4/N$[uS4Z|opT_mٕ#
QjY"
l
7y9z?MRa)UbxG)KL(K0؄ݯtQ%>WMu:gV`+V>ztdL0IgUTBkSqXόg*ph/+_ 5>rv}W*"?)
i,0Tr)+-z4:F5^$JQtIYgCwb!E#`SÒ[k,-U)u-M
Vd<&+X0"-5!NUZUIYWpEiTYkV&	J$eQlJŸU*8T\jHt'
02@|Ykp#vxDmf~!Tӻ)J<rFs!b+6m%_װ[8x`f =fOdBI)0>kE?0oGzQ[4f2QsAa="&͊ʐIvi?Ň_#&d[=?u˞X<l|>mf66}2!:[5
z쀻Xkｳ9{EOkI2{.}2Q
kLDy!./q'B>%NMbgqjķ<ң]O=0`t(~D2
O	{)D}yMD9~v9 [pӜcՃGBLKivus5@+_Qe#lYyRߣbG]{f52rNDy]5Yl<@<u#P&g v4bVW
<o_G.Y;jѮ<D"$Iϯ.lK o$c,qЪ@@l5*!~vnF}ӻX"E$&zZ]ubz}*ňK7U FdǾN	;;),\_"QD+=Y||{8"{ϣ}p9<;C6ntm󇹽l
i<{I/o~[B𾾥\A#˯2<V!3"ۛ^::>3=bH®có.Kw-w!)ccĢ#h4jXb2Z-mײF#X4o@7O3I{)B;!f׸c.Fb/ywX1&e/lrJCH4;)&~]pt=@eneCNm/|)lgJC';nO	w>{:}Ȅ+-R]yR1[ׁ@g/cckyu؃oX{FSܱ< lRJIWImTʎoc\|Z܋kfޮ5]Zhg
{E[:OyIk]cE9Kt0ϣ7?M:N)o')}XQبѕB]ƛͽ봉nIo?~i>orl4ؘ)xR0-*it*
?
yE!7iR,M<I	2KJKKmFJ#ѷ5b4eiDٔ@xBn3Rfol".gܻw!<`uijlo r3*VTg3aeYݛˈut*chYhDfL@YK-DR*/4CtTSW&k*WU*G.=}ʺuRQ%C(E2	T10R\IDY7ʤIÒF3R&ZORg4Ge)'QW)W^?
P0#;]Xжa󛟅fO%9vIѵ/!):|Dfޜ =UXE[*MeʢURg_7ڞZ9)#ZY	
\(x$Nm7q/w6?;ŖA>d|"./-߱Izz|ص[m@k[؎]nIa	%:i57?bw1:<5%2AI6]<ȡTWk=9ɗϯwSg:&E`:n!2P~:omr{"dez[OwC;EwtI"1.B).c~Q8hD6[`!m>JC)+HT,d}fGs^߮7VM<iM#Ҍ	1
) I$W]EwoQ7*9ZTZYc}ͧ5ifP\-6%uq9LW.s]se|3pgrƮ%\W@)sTJ
w B6P6,48G	m4.j~R@例t30!:FaI]^lDL.p3=F>)ٻ_`_=pq_.<!vͦQ7k
$E GuOJMEs/67a~~whvlJ>{j6zAUƌl6`̭K)
UGOqMrAWq?^}-tGHSe_)1 >,WK[Sg?):{W!&SMKn:N\Kn)m"8;IJ;huМ;b"zp 04![~SJt%*j]2D?U/BJ_Ю{^j1
I2CPץF!Ȓ1bg캮R7D1de֘eN6ɟNTu.!$!
O3FfF)Qђ1
S/|'"m$A񗝀r{	4}zWwJG;b[Q!xXloB	3U_H4 ,G>^QQ's^G5S_C+UI@v mUL(Ң|1i"N'jMIN%$DṰoUZm#mw4-[p?rcI,eщ'N7Pp8??l"sgcW7fFP͌(L'34?Q҄*j3Fz=_kn]jAȵ(E8@NJ nTR:CoGei˦6<-7!b|K槎_LGɳKl"hUWM<&D]1q4hqX#d>e!p1>?ߏ՗vqvnpǁ
	 E	1J'[]i=iFX`i
IA*}z}]螑-'8aɡ:Nہo{i7W-aEzWn7.u}W^=<.<lݰN6
Yi]HW0ZwanڮS-l'Xh5,w!Pנn|
zND7t6{b}ҍlpYp5m BNFyN.?UCh&o8%FU2/+\E9/xYE亨$ojJebH$D
Q4x3hDmg`u	JJ+x&lHSO"
1v(MO|$U/27eaLJD2&8W"؃GdpcK
:a+UNR-2Q<gTY&SV&aQKU4UY*Ӆ.5
_مq7.k2ODj͢IgU"uCU5E!yV$1QFNDT2(u
sS4ON=Y0YZ
/(S)sLVj2Tr*pa5&^w OtVb
`Tյ
%ZM=q
3ԩGvd'sHXd^U%,[7|#	{3|gZd\SoK.Dh%<ZL&dZ4YiEUz&؊`"/
XT%HA,Df"jP<N2J\+%j[S:NY	Ƀ-{D)`|XCW3mj{bd{`
]Ms:d},ck;x،>Id}s=???A/A`qcsR%DػStQ*B7װ<6(\V4ҴJ,2yt
SԹ!H2ʺBfLqqRƃ	|ʒb<`K̎9;
d
{OPG[oo?*v
3q|M_WI/xψco>t*Vx~{C2Ƨ/YbM}C 苶1}9i@\jSvD1?.m9ww(6(i!~o7/t8N>qz0oV+w>֛aZSW\oa@e#䉈صHsMIl4LMh@>W}3x{>JYz4= =H\ߵE@ phE_Z˿GAi02%~+g~2KID+Syή1CE|VŴe9P;]5TEvZaXFu63fW5^.lE{ʍ5[K
-Jue6ՠo"%҇>)lئ׹~j(G|@6σvBNfX{'Cj_Pz?g!=z.BfMѶ^˒zn,mL)8Uu
Q v+v0NpGs43O;7J.zBj8	i{290xLz2 nq=ݒ=SY6%6^p6(t# NTCZ>Mr1*Zժ2tPєByS3]*ռH lʟVJ\7$-Bt$<gR%83N"!~c1EFq&x^QYh-I:mJ<sh/UsxvBH9Il,[Vߎ<7|=ґQ:nқIۭY#z!}'5aaHioj\_$5Zm?ꮴm$~ׯ ܗƀciO;v"DYtR;_?uo*mμ< @,*Zr9Ĥwz5q:u++r+fouLN
E6["TDՐ]QY7DFpX(j:唝=yI2-U/`Bv /(IȆ]X[~JCѻ(tBYYf	=7H 
&R8- MEyI ^^D^s/'EьqTơpd9ߐ	i1,tGvvx.]foO˫8FΦr>+7;C}Agjw
aB;WshwZuӡP^n3AHsFo\øc-'J<j*z'#_ƁC6(\=4M`0,L&wn {>Umi&a?iڻ?\8X78[,r]k1~unڻ|{6rV@DlE[yA7ʬC͌O/C9 φyf~Dnn/oA7j*5lzEbn_ksЏ8;\ jCen0z"S$_Ƨȁ̤VmRڏ\DE"w/gZ{h0IQZ:>l4hZR#EqDV+ܠCUoQZoο5i|ks/).?iv湺^ΦEUIñ;uyoۛ4j̠ak<XE=vQ@pyZ!.vLrlDUe#Cg0
#RLF濶8m ;f\
K#`ORԵo]ھ]2Lo/*yKFUP4m}ֽNѷFA)Yv)=:}^^`=\:OMD;&p
N=z=c@ҫq$bpU.ϏCOW"<Otau49Bת 0*-ՒCeň&P*Ijuڄ0)`hLgXLEiG;֥@?x0=`Hzmzt`VWy
ýc
Y6TinX^@%:QA1/H;u?
o\O>6L/o>=lنeu-H\'nNwrg?z?E-sd} PA0(
jRi(kw \\f
?Z%>U8IWOGހV gq.ciƢ%3/%
</
xg~{efEKFSHݼL"K 7aKhQRxA{10BBk~e>gLoln6S:ϟ9|TL{mHBM:<7reY0//iϿY^eVyqV4 @ؼgPxޅϬpQ*0 \:M=rH>H (0;xiD\<%(76syx
.4," ,M#=s@H煔b=Z޹P3g;k.5ѭ4֠ `Y\0/Ƨ[oos"޶hc  Q>;hVؤ_m/7'y:b_nm:_Ev]M5UGʞf<3]ǤjeUCtjST(8L3JK&2[!c5ZJ]cxdk
&~!:c7dh`dC6k>bk^E^?[Nk[Y\X(\̧P'4ExFu:ODix yoն	/u 7鷇2hhQ݄ulh~%-Y"֑o_2ڒ4[q31QRF?ޠe}upw{i,Su[[lڹĞfڪx8-x
Gg?oR;TSEpz[zaXjà`y_7Qp9L
N%*;8F
GјSRqaOm@
ݪEI<"H&7;D8AqH3
Hd"~1,n 
/a%O25ᆁt<X9~I7	VF^d	aFQLZQ'̍߃;Lo?nB}7߾s^y]~z{iyfյo HlT+kb8fh::W᧬Z
(.jՔ["Ph쪼q7@cD-4p:/ܪ9u婖ƕ#~ɟ5v'{/\ځ)<eĐQb[4@AtjmHwYn.ppYXEDG4{NSa>I Sy԰vP7W5/.ބG_JSgpL+\ ܩogkP#
0J^0nJq~`_	[_i~yǦAl/8NUl]+Uu949((FPN$W5Q}"JWsSjQp_Uܶa,)gr(	PkԀUy%ךp[~Aq?Wrc׏ov=m$ao.m!{ڵ}8u	̟z]Oޥ/GT]KK@IL "G~"<"̙{I g~w@<bH,SjX1A\>DPH\`Aq"g+2
oW5%᱇~Q'~S1c6}k?oҝ"݅5
_ i};,gpw^BM	%D[Ƨygt=&$$֒fxc
ezVڐ͇ɎNP,Wm4mvqC|Ɓ{vU"a|t`MEV??]]~4o CvXIQucSGW(7̽B`v
|xG条nhoZ-SUBQe/
-g`~`vs|	o_RyVV
(|0Te"#UpJF74mR /[j3dyJP:&$4f+4qցN[P 0O[[!S[KjgRf!~T%kkVo3{:OC%ܫ^boIԜ:1\T0Q.tpASUk-p}#ԶW0U%5)V~u"/΁U)M;)a*}F2!G[Bo+JOޘXKi|Y~њ:dL(4'j᭼kɂOm놠ǀDE[jB
24ˁ6y<9s垶>nTGGDj\+݋j.H>̪gW@5W' l|z9?WRxαҡb/[sE	M ]=n,"!!N)23
 Cy6QwI6 "OW]3SAk
À w wɄ@$f!ſ*+_z
{a*sЉ2]hB1/Pgh5i<}@3^U-:o?~Wz<(Y۟L\PUB=v%Z>;"oe;_Tx}ǂ%	CrV:L:G1\!M/SEcbˑ-/B7Zh+܈\^MEj+dcװP3w> *! c
-&7jKAePa#҆-YAeO[Z+pӒ(F
@?˱.N:MM͕6qhQ	1{NEX$<r"YIRDAx~H!n"ap?4zee@>)˒,,b?)x
XDu3?sr.P?D'6	e渑,+.&ߨv@
nIH;[qOF D3Qā'(iHmCi.R~`dVGN
&[)C 2	,Ƨ-"hs, j8rEf<"A(O|/3 
HO1Ko9.
Ǟ[T$=ayy&+Ty[QdƷ~+wĚAb~_5k=X-US kJ<ĽЊGȷ|v>| b:lqqYA#
!Q`#F]9./@@9(3ge<?-0JUچ\44BN\+08vY<-x.W2)$<҈y%̕q8MhM1o8dd[Wu[ATMILQS5CkW0T1,YV#u);S)&@}} 
Ks
xONTuehSG)a@ ŦlZP5hNuilS4YOgw
Ԟ]_)BΑ
y_Xvsɟ*:e~	>0k@\k'=~\96FѴlY"sjG*KrI p!+cs=
GMOYcMw^_^(|j<[m^^& "f!`	7y=jHX/ 
cIP8ȑ2
+sz~r3*&S>߈:Kv +oq?iaItcl<69ޙvV^L.M`ل^6/HBo	
W`>"E\.gEl
m>ݲݠw9!ce 1>>unȽ<%_ד3a$a#穪ԉP9'|Vc'pqoLC?6\ƪ?bUN I+4aC7PQg}tߚ꽱/gmjɜ7<#zyf\٪GUYG[tMq17CWjnJ_Д1
(6k(rN"7hݓw['O-IsH9} 
oFZsʹTpl"տuΗ=[u.uQ;	@ c_ks@[[p3xe^4`B#:nn=Z	QM<mX挜^9sjU<ZqR/Q5-Ov'q{p7ˢenQIO,.Pb\HnT^@p3Q2/I=WđHd|􎙀dQ#Tc*-F\;ID#*Sn0 eQBjyK}BPLL@.jо5mGMO-:~CSxKoe1/44`k#X-]FA'_o.,0AgwwBq#TRqLB,U֜WffcGYr7+2#[c[=Ƅ/	4"1t}vޒg;?h9z!}@''m&
i]tB\;1#Ռp]c	!+AGx|?fB
ܠ!9`FҌe%G].#Kz	q\HQ9zZ=@6%??*zx798qo?l4
VEFgڂ動xsǉ-qC5+
`;yfE`H%ߙKAy0N`2I]fXCaL$r(2'cVTK޹w2ibh޶5=br^nƩtbɡVtD)eN )2^y¨eGtTYTu^JgUJ"	H4I\UiEѴ{(RQuaR'i,8.\kYgVҴYJ1IDY=vOi~c==0~7ʋ*V.vӲBe ɄڌOA^:51CXA>L/4dOIlaI:xrG|M,b!(_NNvhu)aX>aO+~VMj"Jwo|/[RamCH'Lɑ,kBYj|kΑ೷g;3zvr]sԿ?uM<?Z5g..a	?x,t!Àdzl1-VZT	9cÐ,w`Gp%f	X.GY	'jX@x:5vΧ:rL{WQF6sM4[Y}b|'6-U]WT(&t,*JyWppZ|#8`.YٝAU8g⽜/o-܌}`7VhBpzߦc0Յ~Waznď!WJA-r9hq`{ǦŔ2	t	T-md9I``.D5Rc$F>m6Yg+FDFiXB>b5e--U=wtE2e_un2^9a(*gRzu5U篙E?GƊ667ߜ)`HwpV2p
 OJ6>cN7GcKw՟{0r6yLz~]y9;_7k}_E,] C8-;΄Zϟ74WiK
uEᛟÇwߜ>LH:cvvhU2r+|Gozx+ux]w1R_;9^W[cCƺ>"3xQc$e|$AUT2SIȅNbY(duU5D:4i42Ʌ˸)3Q_ɰVEQU"p<ItGJ
)YJ%J`RTSQqr#wh2(8y-M""fjklA
z8xs}z/Qh0Y#(фlc{w˾DA\|==/7	(tQHѕJk'˽2lLBPX2X糒*ʣխ^B?7ڃ:])Kc ={K^ٺ(/qＩ	%<NӼZ
3OG7>2)aZcڸxSa*.Ӽ M=c/&qZ幊2dؿى@kDx,cyâhJ
:=jL"86T"Ɋ0+u"L>gI(F<n$S`ZKFll5uH5YjeYqJxbh¶A$A@Ӿ6E?%A0OF؀&`Vw6b" gZ3ĵуl}3
$LϔAtFH5aH@*3a0#%P.dt+S>O~ r3F	vmǟv	׵qP3Iȥza?/?Sp
+A`P!ݚmkd+ꬃ{Ƙkw0'|rыcTvDeMm0? )PgQ^(֩YV*d4EX:j<J`]t!BC=nMd\	4EH(IWY&7J*X0DJ˨ibU5FIkr`Bj+9sp/y 4'sjF DlVOWKxq=DAԦHk6-M11yl
OBnF}a$˯z	T3|>Bi%DfBfs.~e|X]vK#mre()̫=He[`{<$KĤk5M rMtJ_jn[klxmx kEe'M99ny//"eVY%
pt&xRiو`Bl"I!$)@TWUQTy4iQ(K5a
sil)M/J0}^|FPkAS51L!78[Qf'&/> wL;/pvKNx*X96]s3DP̘B3n٣q7CkYTD >
;}q:8>15y;WN6zzS>L1۹[0'vER{;0gSbD%q{I_R쮯'bX/j۰2'b#^qܩ?QȏA5:?|`fIŲ֡{A_2m0{pj/:.ZF0$U-*td1Pꇢ z5l(&yѨ,Y1Pb_ib׺4H{lR֗F+3m?Q/3Uw>eaC>Ǹ`Ü`c$<(g#ꂌl-Дq1`{/ëY	drąZ-Qn.bY,Ȃ1tu[
Bb +>Ftpkz:hogW&&_A*32&ƪa[Q"<X]z t
r
-GN)wSa;o*pVJ8aڴ{Սk&9/!%(
Q"BD29#|puvyE#JKbeU1j}dO:6Z{7?'^//+]ko{Ч5aʊJՉKETuTd"ГwxCE12cY	
"[y$ՠm(ccS㾛f;OW_;nT\,mR}Q*:3pL>;{k3KI@ccw
吝[aĚF?ņ̙(=d;EgK
.H=/kU2馋2I2j"0w$0:LjRĆJ%"EuR	uTeU"8N*U
O=h
,V&jRij*sU*FJBS\<ͥFӥ/>	5<D
l*QPǸ:/XO;)^'Ykx	cX碣r<\͏ٵ@(>D4푒?
%_to(5>$V̦2aǈ5mnb+ >[-o9
&H_lq)7:F4@L@īYS)IbBAg5scȭK˳vsv9؋}˰@_?]gvQKcI~ю 3֚`\у Siw8)Tv7>Va5v_^.h(H{cK]ـtb|=T91Of}xPw}ӑ$	sRGǡ>ʦ$-ӫ7Sܮy  1#ZyrNf</}79V	jv[#5D~q~Oj=OkpG>"bo	%BC2ydƩn_>48QN[O,LRM
 x'H,'pymF=f_O065<2csG^PlťfIR&_ Bx{ j%yEByFvOG8k{&>yd_//iUfr}yOgm?3Q"/;vA3qs16I\J-*cxC? -{U;&WfÛ:Q@3{;8;ra?ھ,vG.`$z?x7cj
O٩W\^JSt6r3h,ގ-d[WbEGe))K8q'97}P(RfE9s/6HN6F9ekcoI kJ(%.0į$T*- ls|&q95:=s7ZExC`ջ_.O;zｉ x҇=_w6[6|/yeY	Qv?vkplx
̊ǹ5*"͓2	D2N]KTK|G
e@Ӽ
XCK/.U&MBdtzՠ]\]tAa%lk琶CzHw@{4[xl0Χ0!@JZ 1uQηuRdkxo.~93-8&slly]R$>MQ];rUir[nb):A#(3O'Nj>bo.A1g7zȵrZcQPeZB$eSU+0EYdUøeYI4!"UMʳJ=
@7cUiT8UZG,E'M*82Ǎ@(DJY=Ӓ#Фn]	ʼu=у,"M.$OKׯ?vFU1rGjxhfm>C\Am_boE+]MV:t>9n\
TO]`N;jg-=Ɗ"KI?2aS̪ReE>~|}vEI=<
q#`paCwSw iIu_ݴQd 6]tiYc@^.9X:(8`2iߋ<V#oe)DBi3YJLEUyJP(.a?#My)ModI6	&RaY5HTiVTZiEu%YDӦ7107|!t*G4_Dz
e%޽O"8PX2mK/?r'ׂPڏLlѱF}9VU9mnAss@@h3h;?.-tN}~Es~l	o4h!	dLJnKK
,na}yCxuN~8q⺼y{4oxSj"tk70)0,zfg*&K|7;.6:\.6Slh#}kma#f:;,~}MufbI35l-8mSE^
W/oO2IR<<o	(ѹYF:wb)9V^Y3_^x$q~:7tϼa?jgq,DFV?{*{.U;6Ҽ&p<kjf m7}-:Ν>1min6pjbONo%xM^Ŵ}u*o{5AuJ^Zwz<[frHirߦDﻙV/x}N_CBi.ٲmn|_mOH39OSxU[sw9􎖼3١cBMɸ m	),QgoJͤx b᷀J5#8̥xG^Gʝ1t%&S)7Lgi]jGkG4ߩ/]"e$ T|6|gH]|yiZpYΓV/u<a/QES:SLN
9xkRkfYE0XM?n3ͶAzBFYքMē t<vxP zׇܿ֊_|	}7/qĺ̴OmWVٜ|k+M<N2lqZxۓLe\Ģ̓
흶-Ō$#^_|hTWa+l¬XJs6clBɱx
n/LF֩!
Acz逅r1EP88ئm0#6S9Bc2P a^Fa&PKOa8ðݺ抦g>^87Yg*Q:9POQoմ{Xnm/mnʲ_A羰9AS)Ԉ]]_/3_R( $m )GOMH .<k	LTUB Bkh^x5 >TÜTÀ"܋(GC(ld~/¿;GZEo_B
(%'؀
_b#e'jg&{[!J3jI`wRaER`rz©Tht҆E*|t|=2v0W>}+׵.7BK	XOF*2x7TGFx0JDyYbUjUDk< ][~*r`Oɦ-w0=#[-0u0al2%/zqtc?,4"Nhu!!ڭk~A
{Y
#W{R^|UQ8J` vjqSt1"ɑh"+fܷq$;X~k=>~7axŎlK	i(݇qN0c,!Lp`mVZEPqby{L`ND突_ߢƥ<Ƣ[s/fJXzciȒ;zYժf{%TJ|GX&iƱYݷ+?
5e;n#4ͫЗo#-9NDhdY2ΰW6eV[A r'W翜pRۢb8GICt埛C{ѱ0)Ⰾ: ӠVd哩"f!\Uc˺.jOU!*̽X¤
دK<)Q:
,WI9`⭍|'闠ׇU4#̶ PUhv*{6BQ'ә-9qR_M;,ˊw-mM4-T,鰰
x)M0phXJsBG1Bf='ͧ{+`Hn؀ɠ4'vJ*U7@=Ow%<vBwe
.
϶ɨJ؄XXR밻Npj xr9窝'4%ӜSo6r?GgÏD8j;m[!n F[k8:<{Lr~O_*_/Xk˲J{Sj"fPq'PugNSsaɇ;̒aQDS^n p
<UX1>W-!<)0)NdISw|_9iǁiVe&+r=aQ鷙"ӅUm+^;O=p>k o8R=FqDմ#!xk?63|1
QlE/PGzB19\iXY0eiWihM]Q<Zԓ 8_@JxJrYa>m+yG6BbHf|EGzT̄"-^~mz|Z=PTa~d7aea7hnG8pyfC6-Z6՞<3+a+gk\ӸVmΜrUbWt,$1z3
tjcmȟo_^2l:ixy%߉5CԬWeSlAL}-q~b"{<XkY-ҲAzCġc6@	QϰfA"Ռ|d1G=Y\Z<1+k,
D&T>c,'jnK
.Ji|x'yv76oKҰSO
 a
۵G5\%F
yӥS[:@coTw:quુ ~g2<N^cf7+<Pc<!f.fOy1.0.jFeS넽t\m]&;Vr
m2\RHArU*{⌛M8I/EȶruMWcW34,c+AJ[QCR9;rN2W+ԩrTsL2g߾En
88}̉NB\tMD*MSވ@VR#?=TmZ ?R`L!(-8ȋZ=Zl
,-O'T-<y;P	P:,$tuIpGa*ߜߜn: ,Bz")swk]-pɖ=Չ7 ݾ"bC/t<q-XM/	𒎯::cGivyNWs&K\T^VU%Gܼ~(>ӑWqyB%UVy,Ci %]+*i2K ?Tuʢr=QzUI)JYeyXGE*)I~+w&S{a//i|TN8X3q C
ތO <\jyЖ(, 8BApqQ$ocz3D4"9$?ޞ:=~wq6'q 0^CNooO~>]Io7՘4M--3i`jM}$qMP]"n?u(_OBbbW2[ҡ'f1˖h-ǗƯԍ@|AŽ$Bĭ˂Ju1	DIœOOuЇbaYspYrVuLTp!1u&s^,cT!(GUa5ی(z^άJDk
*lVn͔Z?In>C,3&%a>W`D(`}ƙ,ODxh#A	I]3A̷ꐧyfVvu^hy)vs@4㓎]ݯ3?@T'_x.Bvn;f_ܿviQZi	'̌ʋwgpсsQ@s^Pk19(@mpV{j
-Kh&]~N`gP!( ֢>W(L&ޣ5agQ EThv\״Y;}eUÙ&bl/ȕ}ClӺ=o#V#@"VfוBku=̲EX6*nש*-FLX­->`ip瑖{wL.:օj#	 &^
W?N(5nccFLFfzԊSNݦ
n膿Eɉ{?e.ΛwS,mzp;1/)L5ϧBɝlIgX\Ma v/\@W"nL_vQWv{UA8sWfY/ʢ|.41avJKeZ&I*,uÝw'!&4P5H@J~O9V.7tWh<[И}Ӣ!.D%?I	pLx'ۓ[B 1hiYn#fDBiT˪s!E,?L@Bs {$/R"Ơ}?3RZscsȦA	ͩy,kIv.G8GC5E!qXHD{vdGfly%zt#_`I6y"1ؕCC[J.]"CeEW~l@<ߓ.AA5=D8*$9΁V̍Nl'5hD]0X&iq[!sB%'0iYZx|9>1;r1q^$PM$Ukή//ߗ0=,t.hř?6o1V: jnY:gQ{a}$3؋x^X5jt 	 8gmƋٳ[أ\G߶c.nnoe+"USuEvzN!tSY+U'HI3.kSS
X0]EҚA}l)uFPOݼ*0OdYO
N!,=2u?`yAڲ
"otߝf6Oac0'q
=X))#_~=>iiANqGq(s/)2KeVQXJW$몆_QqeEJFY͢7ae&DYWqx~粀˫4QT\zᮄL'^s0QcDpk*=[Àn)?90eU(R)2NrJ$㬎`@oeGI(:{I5\<RER%yeUIV>\їQzEW+*(a3*8X|/0a=j$ȑ:cD/JFE:< "to,,*JM8V=]L /\(?# ]ͥ(h(g7#lԏ)@fHgYڌ׳?o;Z4%Q<6>9]&X;74x{#ufZS.<3]y4t%k޼zb퇑)'@,
6dCX~!\߆랤UD
h6wv =Պ̥9~?-TU'D.+٭MIh6z!*f&8U$`sҶB*'*lHP\n[XOz*˸lT".èUK)")1)uhAP%EI:;Y%AGz~W7:c/a` 4wQr*ṷrVl돇1D<ƃ7:gf]hݎ%=`sTk>0ڻ%i<>J3mp{Aᓿn-Td1\5c<		 }6ЉY18jͭ&K#l+2Ö#BqAeNSR5x(T7{`Q3['}ۡ|Cf'Ac}:oOon]lio} isXG6`kX3F85w))VR'
Op#o"l>r1r/%'jBi|OOLM)a0
0lVH
smKjA:`gPr6QY9JiC%}~]NTށ-
J[a&H)ΌͲ
S޻E9
ة?u*n\2tqK
4Xd l1n;
X|`,WfK?޾d
J'0申

ꓟLy}dx'(:R")\XWu)ŃtPZZƆdDpl
vl]3'K$FU'+3GSzFZC
\%5bivu-	~ЄVKa-%ynFJ0X
NU/Mq>z5&G;efoYj'7>&-5&W;a[ÜD :PұֶHKV#.Amsp? }݇n2:i>z3jYZZP QU5.jkړ\4vR~jYtT,+wIu8LB%!:1:N涎:m}Nׯ0Yi?]i*~08S~E6<`76tw>ޜqDͳE_~=@|C[MO.^Rf4ȟ;<^%(}9_=8j˹q
֧٥"l'y6_utudf!tdk:A:nFвTLۗ43N珇殯Ь`:/,ZEîuiwg%K-@ 'Qz6CJEvGʡ뗈eyPaTi('#VYiARt8-ĆB|,\VnR1+oʗnBL}g:8~~=/޼iQnd'9*iDzC `Sݭ$ѻGcwxw7EY_&:9o4R#	mJ;{mbo3;O
4&ې3
ō)sѓda-	N*hAn6!
{)4GgL"kDVcc
&efg|!xDPe3[H]H`HtyF(`:`$?[YPDKd\/ =Q-`|5{0y7C M Y-vu-xsިj_ XǑA%@r|;ď܌BxǞ/,R"EB,L"*-镢J"Q^QFEyxiyI{?"sߋXB_eRd*Ԙ/dȈ4eēbFώ2vTPsؓ7Ն5HZu*d7ÕPbԫ58,4eTUZGu&X$u2)<ϲ4rT׃ 
d^:HӤkZ2 N.(Qboe'Ӹ,Pm3{>_3+(7{qGJU]@xm9d
	">429芯~ЪaAn_th%D>.$iZQaUx0+DY2N(VuA"WFQā_zC+#6+/5>ɫ2HRYAg5/=idp`hy
(CxhAq !2,Q_zR^%z:ӬD'VQIa[GE2Xsv$*4(pԙe-( 	4DUHT`*K?"={T7{=洡
Qj^K<a&(*('#/}j?9 ɪdb2RX=RV,RA!D$~	DgAZuVO_qiUa)-rY^*V/pK2.S0z?R=럥EEZx(~oS|ӌy?I@Qq֞Boog/JQ^v:WM!2=#d.4j0A,2u\
EY{T'`!u	$I[T~QTu	O`_	'i VQCJJ`V	IvjE&H
G{bkܸ>-W(-:s`eue>9U)QFS1.l=$fVgP"&	0ϱXcRD+or<2
֫GqYE4й9J<l%pKdjvG&	ۅ4OE;Zo]rֈG,aC'nc#_v5Ivu%);ORԠC;9aLsOaG1BSG	}ѸzD$z**6G
'27'E^Æ^+'}kΥtʛۋ[5if#'ۈ8teqϦ0Edr>Zn>}hiGֈpԳjksʂV !\Ts˖b7nq"PMJUU[=M51bh;nODUB85iJMTi 1w7ڰiYQTәbwB:eĊ]ɴП]05`n{ OyCgmx꽍#FAo<uh/zJKe"qn\N=k'H?`ﾳM`
I$;kS1I4+{62
nH_BcӴ2Sz)&rŸtŌZU
A"+P(miEc	}uW2Wb;Nf{5V6F:_4u2L}\qLSwt-P-!,`]8Z--Y{ l۪H6 Kh}p;U(&ȴ6WXU%Y0A[yq(B
wjtWE2Kp0XA&NtFKMU瘯1^?c?ҴUkhA>/	ϒk^!<&/EvՈKHY߈ڿ:fFWjJD(|<CJ{9_
0g~8
2G2Aʏƴ^RI,"+r/	d%"Yrpee2D2'~qR9rQYWUQR$݉~$"JدBbOp<:6Ǝ\jZ$:gJ)q#lA~9+j>:zq݌(WKD1JI5Yj1Uͣȳmڛb&'~5Dv	P~юg:LxiQ>~XGF<`dXf'hxkSۨBA\ݤ͐NZJcL;Xl?9OUh<٪'])B|hǣoyE5}wK B/8uLQdE}V?\&%,dB96s)Tz?9CM1ng{,u[uT~˵SQ_|v>DS:% (_z!Q3Ŭs#.dLjր26?ƣWJVuafg{/Mtl
Np$6;fO=|ay#
:y=qEc;_ygZY%Vr
gRT܍>Rr`ZdX|z^XM؇#GF
zXlTL"*7Qg6q\bayfhXIMUob5CHQ6s6JFVmv9tZYגޖ,R/,DZ^p:Bs6dlk,q,Ǝ0HzM#fv)y'lHiWGIsÎ4Qq[EOYy?-aW[etLGZK<	ҋr|=bZc
xn*U2OV\ɘJa6n7^$J)#T4a[ӆW"d8)d5T
{IQ?>#/EUyadq&eJt:LN#z"(`eUy(P2AUuRN3C2"iWI@.o36	8ѯXh?oSLߨV 뎺c?˷ `G'AϮHh:Ŵh0`q)=W_[晚/cʦuD:Wʆ}9q9Tz0wϹH)׮Zjl}`n\&ޖtrX8QWy
[@5tJz/o=xC¥JPgݟ(u*C?q;=r&C#'E$"}qןHEkt{@I{FaKL<FkW9SĶv]E2UMG5ƽͦjWOOLT~~3wѝѫ\]±Xb{Vi|o.nxYo,qxzծâEQP]($SܻmV6
chtLH.HӶ 6o;8糚5Q2`a^,lC

(c>PbrD
Sc/no .M0p*7g"u]uБI4uDƢ/R||1&k۞)*By;L;%9
c0g 4O
[d_:YԥaByV
@1~4zx>K}=y`^)0>_hOPˏ7&>m8^
wO:{3ǁ+:5ڷC7*vpl䐢inZBPZǉdԔŭf2;&ʞC9|QYkwVg?݂i;FGb%=]hEe$Z-RW.~K	gD>pEnf2HV?	,сI
2~UI{$Tb.t]ǌs5hL?P]]t-SށyShQ ?2(6W}jh2BeѠ6rhEaK14u>Ay5P}
sWF̆®?0r02:
Vi	uQ#)6aHKW"Ix7d(XP`yQ8LI1e"$pQ{^%O8^\"KDqQ22"?*n,2e^ \VIXďt4]z~2PO<.KQҏm+Y|k!XOT7jM91A5suв.;eȊ͝)_<n
5q]_ZyAZ$~XDM+80ȗ"כ`>֚g8Vťfȹ oc|_h<AW5]ּbq (`tV~`SlIOp=on&XkjPp՘V2:PANGV:1?`JK4WL岝ϩ'2EbVcn4i7nIEG-K',Nl}Bgi>R
0gk4.k`Љ^-
7+^Z
XfS95iIZh).QޜJZ\l1h!go?D$Yc"aV#e,OP ]@XQWATIdyXgQ}B<<Djh˯j$-f;9M}BN՘I2LЯ|BNS$k`Ыi&0;E乌}sR@z8
1"Oڋ<ȼ8TR.4ϣ´0$(Ы8"0Q	Foeq
@r}hV"drM{h͊V
%7DٜPF:douY*=lf
!Jݳ4Kc}&|>󿚞]^ߜN?Vҳ,$x.A:#

Cl2	G2N%5F8YuB2ٟˊm5BMn-/2EGdja|!ƬFc7f\ϥ~oGDT@·ryAwn3hh}3hqe"UFa3jnlӂ
}Xwd=ck(d$d1[`׺W\fi)]Ʊ(*c"W%ʩ\rO)e=NS$!o-
E5;fIx{vu{9*N=zs
!9qg{;r?#>ujk&j~	[?DpV˵>l{Ӯʝ?BK3 m!cLƙ`F/.o/9Q6ⵡ9+<l\H+&LDΖiY)Qڍ}c؆%s1<x<n:pO
@Sm归o4fF/
(楰zWvdXq0k)y[%l08=+ҸS?#̋(HeeY-YWYI^e^9IWEa$.K6㒉#9 F^hn0
X[h=ןޜ
%KJ1j:[JXRg_I&(>Ы,,WXS4К& Jav|S+?}v~n[7ѓPa*L/W=Xo K6}{[526=tTUWAשe"<qoүk0IeYfgT)8xxyUQQ-EIeAYml"5WX
Ԍ6stÛt&-i#nq³PLW)]|gbDtVB	-+83{xy:?$Z]x0Qh*`aB%)UA#wnMD"Ns72`u1
%y{YsTTŲIpzrB2&Yi{2QJ;CdAe<eB$3X$(#YWzi$"yޕqmw}ol@TjX,'X[s~!j8%1HEz5p/ IȢX^Uք6iEsDրKWfAY-xDp&f[TysaT\Ԑxz+JQwk`W:<=AQo6Zl`bY+K(`j CM#mpTʥeb[
uP-tpV*oc	wWuk-iªd58gH܌gEY8r5eP{rj+DU)G}Z2XFmpXহaX	5U!I쒞5ftX+>r!OS*^nbMI
e}1SLPa..0sϖ7 sϖ/O
&[ 	}-+HW-pc%gIJh, g|na۟oYk-tcr;ǿYfE:[!#
~ c~jP9-͂}}a	}<˂(H] 6l20=TtPnn/&'KSQX6J(s78;
ʮGwWdxqu{~ssgwCλuknܑDYXn]`d6
HTyp"|ʆ'fi2l.kZ;Iݻӛ՗*
7"4tӠ6G9cNԽWy^iII*\'Jl"!D$WVUN\0D5
%.'Ԭ
v-q]hv+p3$w -L<hH0U'V]_/JE")%& uħL&2]q_@K^VHSX)gifyn3rH	 ^>o ׬?XwoeJAd~t[i4h~tx2zkᝏϮ/ݮ|^
bn>wKNHn_&5#ȵy'k-3	YZ`t?*-PUeLﶘP>-*q"'l̃B㗁B6Z`q@L#:U*mD{K1B,
4"밹2^ur@*=EDGNfL z̡IXšDnGeTYC!/7,2i厂PĕnV^T6A'v3ީ:uٌV;=m_9`cDTb57mnWĬfESY>˒_{O(F]3N)ahtF*
M>hqkrV"@w)v݀ s2qBkɧ*/ 0{.(hxyWNaIyq^!'2J$V&gݰF}Ք28( +^.e$9=&k8d]I޵XIEL;?p~vy[/uN,NΤYxiǆ?'{$_xxiFy?|M͏[" fi
fق(o[H&*K%CU )Cd4n!\IF).O~lSSTvAWMBX12SoOĲB
7phYޤ7gx-IPZA#+Se"[͋t#~`Rj?O)
E|3 ~*bB)CM[	a]J2,e;XMS09v O0k7k:xb`
Ǭ5L 7<6:܏mBLr,&ТU
"Rcwu0J72&pzp5Awh?L7b>?^-0;d[UDvsUygtd:FSǐ/ꩼ7U^V'3g4T
9zh>G)QD%}(iS][}g䥔viNP&Px%MItS-࡚5^7Fgi&{1C8djx@sV^P#l(8:m<Ί@d"\dg4|Q9=\"h$*4	MUSպ4@ $^_U+  7]'D#*To)X-D>p lG"^dExv D9쏸xS#	'Z#{+>N3hVME#KF@D	-ʹn[-^mۋB &Ǿ:ם{f::"}}gX XX/W˭7.J02)lh9z0ؕuuNlE)_7%f7@L>)?^i%ME椅p"vzYDĘmͶU3p
[ZTП?H}pJ%KL&0Ϝt)y")?-8\QIoڲ&. x5(;,ɽCoFfg2-Wo6p1.R&]Kw'u1qkkia{ 9JXM)ռkd&-8ETPY^Н_gzb[k	zG3_!"Y"M0v$ˋ*ܸtJ/y^Q)6A{qX:~%q /7ݬ='QVH/'TwDz_
&2Cޝ_H,z<4[`"Q| LT?C\M.[ֳO5K4yd'>_77oL{ke]aBDRS[(I-{8/ ^Ok.şs|ۇϑfP l͍=Mg0Λ67kr BCH
jMPikɲwN^7	@aM戳YǔL}M,Jj[4
Z&K9^k<򚸘)l8&sRR:	`8Ksvb[_IsN"o|2F@@(=E}?1p5u~&>dIS6NTMT-'3ԛ 4e։W+LjuROl^;&VƕJZ焥K(J-b-Q1%,X5faw<[l2:!ڳ?F|HfѠ,Q-	
yTzdYRJ3j$m+"(O#'e*)	MWfφuOJ;
VSULwQ`E`Sۿ632J8Q`<[ ̪ad22 R{2Cf(Ɖg\C=!g-D14d^_~ 98a"4x.H3ƘPc:e,/!f^$Rp_G_J4ire7޶ToOZ	y\K?i*vlb*FhQ/יx<cwׁARTEVa Ic'2(*/2.S'nUy4O]"䲒yE"-2u]/
C3t0P``:L7xAGȣ~gͣ#	 ߗ&,fvv_4pQB˓!?~æe^`a6+l1ۧ٢|9$S|)B]
QW:R)&6)iϳ"q^X䎛G`5֗=9yĊ;3!7*CYPTĖԙ֛ڿP\:97HQeYmMv̹ɋqVT &&am0A ݊ְa~ pٟC:PuIփaV-Ǔ"vʞ ֎+xe\cԜuF
,Jfi+Y{~eؚ.4>c>
B/ˏS74k/q&~;h7z&S0M4yCXkGf)fyw5*裋[|pàU~,I]k5<:׃BTۃoe2\
8c(WeQTEA$qONডRl苔"$MD^qDWnAT:N{AN{?**~pRn躹fUɍET乛NI_'wddSYRǾ)H~C3鑿3#ǦyQ~^yI!b
hF~ƪ˛>wq0qͮYsioqLh qvXlwv{n/x͔|=`]l?ւ'HG?ɥ|+Ri y\I#y)l={d=`RS=!ѥbXM#GCԘ)KIFEku `6	뿊=.e6Nߠc֐jf8x?M@LH\(F@[Bk7ֶ|D{띄 +R:Bg#|̃[6F Mg+Z	,^ys[|VcTF:uvOȨTӷ{\M{1(dA  7ɍ2 ,Z⨮iXڬ!AH)Vi\hNaM>?ۻ˻z;}w-5#劤{zVcӕ4V Wꀛ=a\`ؕhny̓Rc bpZÓ?$@q3pAL1`8Scv)
M4R 'T*i_#(11Wq]#+)}CѴ?!ar H^ݖ4bteȸG0VX%͘Q1<n9x;WQE_AۚWՖ.ݢKG^J'iݽ6ubpA70)"# Z*DZA],&llY/8̧{KAP+뤢L)xQDoK|H^Tl7
&젠h J$)=a Qq%>
f'K샀b-2ݭ?JFn7~<|FBgmV{8f:_~@+ϣMIG~)8b"Me@FAKW|spڢ}cf`
,ƬD5%*>u?z{8c=Sn>ۨpEØ&ks 5CfF#cXLgdfLmFA+в~u۞i}!=pW֑Z]ҭ}G M=.Wow7oCC:@-uj#j0<EWOUk߆ZH#}Oq@o	nKV=N|ƂjkOx*(->5	DȒy@9	'O`:aY[.Ur['g)$ Lˡ5<62eq >
kI:PEDq0t=[xlD6wWOA1Zd`B'=k#\
p <*p 48DTA"ofl(E^\ERA9YnI$2a=w_)q;/,Xṣ<xqpi
ANj.WdfiD7!ף[mhH53\)NVU1#$e-q6¥ͻá:ꗨl~&4k=J>|u!ӳ"e`РK*M/[h"897,II8ĩaE$4u"-YAԫ߫J/Hd2u2r

//K[F%ke'y
%NEܪ2VW&2VCdPw274fIai}{
}3{f%R0$<O.f'c>p_hW)0ޡMخQH+#u%zF
^=M3<i:VʥF
-8~U)P|hJqָ>̍ɔC
f{XFr"cB%FF/_JmdI
ױ_^޵d!wy)S4z^f6BfAEaTuW!JO(Ҏx^l?S24JH=D+޶,}~LfMcqIdUnm,+JI_zNEIɪuI%9na;g 䁬D~:/Y)i؍m-[!9h,xi^\Z;Ȥ#Wa.9}w2ݬf_c&K׭bo\"e#~<I`e69l9MƉpߵ[p^7&=iIͦK~QCxLУբ!Z4qCn
G}PVĄƦH!IK|mm~_!4&m麼zp諅kLiÌG($M8Fe?2#ᗾ[ҋo(wۻn55C{3g)mt]3IERkOٔO+Ϗ]4-*.B^&s/姭'=̯HX_1ągBZV<~6ު[FmY!Ҹt%__66.Ü)߸%0>f %8FsMO+5ݼܚ	y_/SaOa'!]|ubPʙ+&=F7a]
 Όʓ(@"y-PEp4,^8=LLJ(G5eZ	G,-"VbŚMb48=sXݽ|l)Q#HT!-Q{tgvI\k)Lnm'wdyg:e29Xfd kbJSrp|v\⿜]⼛4ɦ~.
iBD:[O:Aj@zxPÿ]>YEOOH:+aIU%QF\EVHa
穂-f;EʺEs&0LEVfVW-cīCrttS9N)bG0D=u[b/ts=JY-&[=_yEa"!čON+lrW3>QŜYꒃ%| %"v44IX),ϲI&E:.;BZ,.2	8MacQa'yD)ydGv wP=EǻŇ4CmMNX(iY3V|6Pto8H'.	r ˞Hol50zEz$DɃ84Ɖչ|c CFi_RQϟ˺t{yL1i:6U3-l\8j5+	Hia2 ƣ#L^|4a>"uq|>Žw8&A#+\Z>:~."&snI4h:GKz6BDu@0hKtMdUMKQ99CE99B>zX\H:<ҏou||d;΃q̦=TC
K,}L&ӎJҷ,&Sy鏛BWLN Kw۫hm׏\}N<b+>M{|nt$"$htC30ORL CZV{CJn
gz0e}hfTO~\c}'4(XF[oIdMX/pջ[R}քWv.ƯZ%o90/wisiSlk+G
w7U/_EV
C%8Eq$"pC>jiE5ta,"*U4pD@o_7fǴ~~}3Fi=ϐ_o-cSQOqᕺTלzꛯ"ħ-d{D|6)	ib'ԗ[a`Vɍ?|kI]`jVPS
T$f
BcTKN`GvE'Nsk&i:4\D iNOTl5-fMl7Sq˜92X!59"c{h2IV0dhd?DtBmJ	:3\jnuBaLB^#;	/T
Aj¼k&J*(ɢDaUGa*#ˢU*E,+GiC,\moj/lz{Ph;l<hdBXyB3u{^!ą5e"qɫX1!tgkGnmxV*7l;BKRL*PL!i\煽mGlvO3X-<A^t;Vq8IUyH2xutfI,ʕRѮOE4*cPs""xHm6XezqNR?7nxsgW痗*ix]lx߳EDR 
˝iAlޜOs9i.K_?fxyu5n5Zf#-UKy#PkH.m(mMEv¢ r(JDHƪ"VQZŊUXu`V
wP2Y<Q`
+WIY&2)νpl%zިiLot;MZ6.g5+# bMZL%*ݵB=M9ߣIu3`XUpb4NV:VJJR{~qhJk94m5vg
UY^}2
\=W؎q@O6;|irFS+/(/gjy٧I¤gl0ѡ2f'͊zG-x6u=ȲUO?cX%!= $-zθI)oҥ5֕<H5/1$UG ]S4
9j]vS>.ƘE~&[a6Н$^"P4LElMuۮdU
^F]vZc8.EcD6e;;#*0
akMCLU=`?^ܤPn
'o"AtcnKZQ҉DyDHhPR_@:-LH&ҡ'Zw"b?cݛr˼÷
tfs#$4H<¦ؼodi|
20wZccH71[&hDWb!Vfv^zIthTlxjͰ%h\l6skGonvĳv&++^ 7qܶW|Q΀!F1{L@XcAؾ4!C<mј=O[pl"T4y^bCq,Qop#0B"?,9洚
2T;^\]
 ^.=Q8+ei0
19;$@q8#DXeR)+L3HU%dka,\4qUETIRT*QU'QQ	Ɋt?8uw:Si;ԓTmN6>SʅkNh].nJe[wť~1H`W
4&DEkm%Ӯi=.i`.Puk(<	?*L2UK)e(vXJ.KZ
1Fi%TD&䀹86s;GVQ\ }ETtrG&KkQ<p|_X0C;O5!X_Eig.yg~4@mǭ$S%E귎f4~z8ZWn٩%НfEt6ല$Rd\",``ߒLtw5~fim3nHVd@RՏe6jA?X3YxDSm}	x7h$R >h=dx*z/  >fGp
 _KQ%Ci61	h|_o&^۫ۏoKj/ >vōl<X*kfK~\b #c4q-HX``=쳚tS7ID:j089Յ@c[2CwX"rWrxoo;RYyP ֶ1:<HAX&Yc
a8v/mZ[܌:gq5Z6]ApۍNRM76` cJR/3A_靎|ߨC_hOm'3e]goKLQf_$&NJy߭`%Q~sCn8}nM9."VY#RҦ/kHčf6&`Q_D[;![q<aF.tga3_=nucO5~hiUlw*x,cy-I޸:&]uBF!r(HZ4|wQ9ϕxk^ZQ`Wݭ/4A5(<g^`DS
}q416L$fW0ƍA$g>"QI&';Y|= -&7%]Y#F&Df𼜔-26d,d۟^&_`W_6sU[Rҡ.ѡ,qVlȎIeE9OY,y$Θ
RU^BJ%㕨Ke&YXyD"gI,!2,LMlq`q9>/_c|3ϻyng椎l'+GM>-廫v,1:1M)F5"CRp}D_p~qj#}^:M묐d.Jq^GR"N*A4̻'*
=+7A$UbP$q\(lஓGI	Td}fq*,HiVWUB&QR"y",>dn#9at5gi<w'Bnux
ۏ#%E|\oNd393ne>[`S|'N9D!{baZ%sf*EXeCU^)He"**XU-$`HUq0&MOL;-Gt\˭EL@ARݬǓ8~qq?)Tdr|vC@]#>KrM5|!mWH*Kt7;Nd.UC$S0cPpl}3BQEa
'7bce1&}URhz(7_I_9&f(cwˀw.{\f٪h?Ԧ1F5-BBl[EއtY1d߿v.'aV:ͫSTTU0)PqdwU1ñXUJSU^,Nc^_,+C
+5\rP ([竴Oph6*)A^5*ayIl
CT}bv|Dd<{9Rm_6;.:cVZO
k2]\1[w#-
IFcKɮš<ؽTt	o

V"wcl.W7Wеڎ}ZؕK[x!]ҭ..[Sd1HkVZ.liC9(8۲t[f=vʐ>}*@8	:@`r[_7_OwbqUYѺD"ם
8[&f&C*͹Uc3:=[5xOra[1a%N8(x(HJsγPe\K6Vk
lDIGyr8(j"S~_(H<$(z"ρ>Eq(-0Gz28>l/kj*{al5f`]#ƾ[m_&Qz̶Muk8V1rɩlbvb1ܙ4JxZ=ife	V4˰u2fyeyg;DwWܶW8\{J/R$Ȗ2}a5
nHG_?}n4@pܗI ^~9xsyIȂ؋#ioB$̋ċz;^Ets
zX<6>b2 QtJGSސhr!37 Q qK[s=ϑKIyKR(K??2pinXʜ$Bws	+툗v4ϼ4Ȕ")M)5ehpR֢Xf\e.
۝)+WҞZ1JC}BeWs7*/ E&9F͢$!jQv^Ph:Je1v=fQ :tPľZ!#H	˒<IaI\dIr$n,
<ʂ8"+pP>]T*G	{Giu)V5ZUE]w 0/%.4Mʀ)ITDXkW͚$G
^Zi;\WĚifEA.-4kluI
SvDF
ZhG@sx;#t&Lb:ĝ:G)nHuv٢L?!{/1DUCǚ%V"̈́waRu@NnM.raR`{Wvpp<%[M'Gf&ǇѷݦhF%&"Wz<
G'	w$<~ۍaWd5gԒp4qϝ:uTmCuN !_FvYQ (eVEdUͽIU9U4[НCW#Jh;B?׸>*`k@Iv۵	}8,b,xOٻ;Y~D<eIo|J*,Mۥs5m^ޛ-R/!4@{wwSX^-( ξr19Bz%a$cmlWm eE|Y}|]8[Qhvew$yGSRmk)b3jX(6l3[9XL˵ (ԦKȟfu!eWmQL9i,˅7GYO+5i/J@Ka`y Nqh'fՍ?9E9BCqHk]2WZqA:˶݇OculVs#̥h|~ce(XQ
4˳L	
+lKtQD$	4 nxMV
<ʴF2<CF4=k72{THPӚ>Px<UJ/rv`<G1.%!xJ73q6_o+Fꊿcq)rg Y2BP^y~Mb͟oo-
ML!hwB#=׹Md-8FipGcvtp7FJP?PG2%vUic\l`sA^UP%M4ЕB:xMsy7GpAiwRpWLg/lŕ6uOi</9D-r]g^Bw@ӟ,gA.ډzq%,Y"O 	 Dy_{
[S	p{y0&ܓFZ{,8J`+0Wpz_GQCh!S)ZKI{~+gqȍE<q׉?(\Q`a>0{n	+"9L`^D]O?VUIyW@`dӄesE jJ<<N(Fپ-fcwp,zh0R7%JA|\:h )eEp'j񈀹I̏GtG5-SqetZM+AgѬ"Yj3Ǣہ{<%fcH\F8N]'pK,U,`E(ׇYyAix{t\=OKnS[j
ڂxqpk#د+elrXMU5V}So&B	`E&1pW9{[76j,A@5$MpP8%74C?>" T}D7Ϝ4ƔA\G>t1`dN>^i_NI5>Oni"$kұrx2;r~W=U홀TZi(՛;*kǕL,R/օ4-cXfs)տ DW)Nz-j}9[zԙLagC*㒷p턚4-
}C<540joeW:zV癴ټ4Hc ,srxuL, +(Y,	9
K3/.ROǢ$/$K8$B~"TeZüZ؛[5&фc8&3ρp'Qa6-:FiK礄kjG%De]zd'\"	|hyrZrvfmq`50|gp?t]RD3Dl3U41Xc
hzcy|Y	d _|q8YB)CvkIF*
gq6Om-0L*$d,E(8@,2]'Oc'<wr/r~
%.(X)1]UMKt|0ھKݦ2pvSN8 v6oԏ;	h8@!ml
BSVٸ\Db7 B>6`qQzV;ZܤHվ]Gl8{ünedՊ	(멥n~<ѯdh8{<\M޴D'fXZe3AߓoD2̏[L@Mb'sBs;x7*"r4hML`D]&\O㚭,Qxb_T1W]Zȿ4TL,olR]wRl͑F\y{^#Pf6~ԩmN7^1/OaY5Y
jAhۡ㡧u"ȗĜb}w N@KY{%#4:#k5>XyLոV:_%:aLwTYVb2L,ڎΚ8"1X6hI?\§˺2@
Urf㙄O]]%V2r 7.j7b~}XSGͧ4,)Ml׬'V2!vE$4x>-)M&X4<ըVxBjm/AOQr]spk8pPy=<}guabL<QݑjEjƒqvD8HHm43ue6.<\7^Bw]㮈ov%yV櫊3HRt81~a\d9ϋ
uoKw'Kl 
+94nCK(w։^*vÝBeY+훬Q

t$x?ȯёQe~&{(x4֒͟` 7j#Hɥj(^~#;|)!⪁׌hK4vH@jz!3zȐ"]Y
UC6P~ 	&Ɗ.,L~|/b31WMwZiX\we$@v٦b_uҠB/r'BkV:C1Z~˜4(Vp$n\N0-,F9Repz<rngEE~åRQ;$QG'0t
ȴ<gJDtqRqx"7&_{΋,or|߇]L4Tm֧4jO>b3uV5~.gB[}бR[}7:\).4	̋1kjxf";n(@ojCHPB<
l]y0~}-ULa^ݪ9}[b%tG.GS,*pvHǅ 	v-aVɀR<`ʵ WVBu6URk7A{[ɵAJKe>O
M1şe
8H;n=䊠ԥo6
Ã^߭Xe Kz2aLNi!Bvꔒ\_Xj2ȿ]h!-#.Rv
T+ݑ]c_L+ l7Nqy5U.^.2ȥMJC^֝&&1 5YII\GƧ%!AD*.kS3Wys8l=-=+%]/nipkk#Fpeحv왠Tkt|rYp
*'~gEB2yV\[
Xȷ~*#f#bh9Gz34lT
Ё|5 G
f|jsE,YN^iR_XZ}KTBCYtrƘɷCaK:Xkv<$4 Y.#ʹ4J
MUz
!ۀR$\3Z@|ma\6k$CW_6.~aT7
MSi,WYrbh1@a~ȚTbI'aG	Gm3S7MaP)P$p}׀Bj',Nr*I Gn#xysKt_iNK
@!j@ 5Cb*`
DxԶ uS,eIEiuh#Uu@yfTy~;SqAYm`a"*xց#~q  u3籟^RQ1˳gnx@ޜ7S{<

'r,Nf>OЏd,J;)
"EѥP(HIJRT) 	C"UZ+\]thoVC`ԢmhGH#*CkШrptEEyjpᛞ'W-ʎbRE͞|	9o-z3ͨ;R[+ʲß&xp%U;k|ia)yRKOz<D޷X bJ	2Ӻ$G$_)t_cwES`b1~TEWSg,ˉ\ѱ֔8YA8X[ji^7?( Wl2NkEW?֣|(`mClGrU*gUsZիmw`bl51&чɇfK=J>oA6m%it	߾I#[M*949wy@u9z|q|;O~c<D1DuekOCFDwsL0[8\5Ba[m $}`m~;qlKYy
4gu	K{i1ϦK6PAowV_J /)Aݍ`ϐ 
,d]6F1! Fj@w̉WA?7#U[˕u4|9s	拴ϵjV4
2Fc&	7okmZ;y퍂,A-$N9y͆}A`C
d'4<9YY9AJ|5rYo^.)a,Wa(hx2]AHd,GtΓaDE*H\@BȍF=ϚC i/\@wuuEk hJ^+2TVy9[g{L" 	[ʵ3A~38YQE҄!p5,1 3M)- p(hm{M'B;Qsf	}XcT7szwXXEpJZrןյ( E htЁ"d+&#;ɭ}Q7-7>jKoL_*jd	[e%41%MC;znpH=eȃc~(^S$+'0qs={]1TEn .|bKL='9I@ v6z~}硟rg.^d,OR74ȿyٿY.ĥaOP3QWscFYGi[16q&*E%U36`d؇V?mnɶEϭ_f:)e32>JRPvh HABeooߓ H<Ϻ'{X{p6Cpڟp|GAA~HMNo4%d:f[Z?;CQ,R1uݰ^8U/Ө|*uf/i!:K2b$K%+
׌Zfp	ELnAe9v 5CF~gОFv$өߋp4dؠwobC( 2zk]SD_/?C',Nj&(X6Xrܥ^Y~Is]4c%UE,$5$
P(*rGjڤ>`Uv-sC
w{ N0*z}5#l4̒@1oӁz(uKQ"TfZ/NWMl<ݪxNt-ÌDQ{WP͕͖|K~ȷ/Ϋagņ`r!J.
r%!E%(Pj~49q'8$l@gDtzpvDARG7,s5grrziN&9&)⭏&)L>'?e!ޖ(RQ <\j3Ѿf0@g9;OUk|?(l/s<'V
hHD/@;Q]rA
AL]Vk@K6ʨ3=hByP1{Xr=4w{T0^b<|cc^=КOf(uP;CQwz͞2	^^F(p,1˂	嚪}N㫛f/fp-uM5Xvg펥yXhFՕm	We.`/l"QҬӍ:H-wޒ1HbXz|,k2aU)+c<nʏ!FTIfȕɼxp$~<+,'Ai
[=55	T*b➎{
y?)|4q>,𨤈mz<6}Rn>}dwfIq39o90ny+^t8gh	 K!?6͍^JtZH
yJLo$殿U\ED@iv Ѭ
Y3kGi*O~Ee=`jkIxF~(I\Щ:"eo3Ly}Z~957kim]
UBվvlp;N>ѹVXE~sfJE]`:rwgŹ 2maGawwA
3m ~Wo	T#?g}uQܝa; }5w˝v*$:J%+uQwwhkƲmK`k
M9tRX%nDVS_}L ~`|0'jaoZ -9tpe@Q>m|ϳ*.គS,ЂVGt0\%yI4Ȓm9puy~0X:6ḥX#kJYcr"*dk=Ҥ1GAȊjXG"(Ѭ.* y~&F*t>'ش XS<MbS^%1B_rI=<b<>Ǽo.?^A7+#ӑ-mTG|/
`ѾZTn!NNht>,#<ǨMB	)[Ol3(lmlb"	&4/.	;W.
w\W({'?4_⫋S6[7ߚⴶYX!bĀ 	.Kͧ)u0v/~Тi_'UTk8=娐:۳~lמX)P*xg!@lTK%~ӛKxX (rHV~~0dGq?J8ln҉;^gHy3(A0ۃ^<F^w`FN)S[):ezE"5
i)͖ema6*!
6iBp{nfdvERS;E+l>FU|
y԰wLQ'{yW _4)VRwTA2O {|RnVwB_YDSs\`
M&ALYS7pnv
N}@C$
2;zEZ{EJŽT_Kl\5crxmnk[D6b8ʛ'Ȥ]/w
:zt<4jQr6$ay7Io"]v_TՔj3\Ƽ(9R	+l҅dk-*YU|Pd-CǏkgӴ`hR|\ϐOeKlh}/rXJ`>ӜA2w %yw#8uKfȮێQ;T\w|j?t  L O#?lG~?a'0Au&`tɮF]A􊜌GnEnZDd֪=[:߅Fm@=P[ W"KdiBj%/-Ъ
e&ʉ~}}#I0xH3ǽ/&>!zQÒzlC08|"ZK#oxbJұ?ል??^^^6,x!p7.ɠ%^"D*h6eH	nY0yd0hEKb!![a4?M?Eôz],)$lRT9F/\7gw|NvdYWS1:dhfpJ)O0	V
F#Lix݉z,wp}Y[Z>x\VŽ(sb]k=OAEiP.\x-L<u;RTjߏؠB
Ye`ZqBMWpk#," 
zԦfi:M[=qm7R3 arY>%\PnfF=j.$Sbl7YMk8[u?)1*Q't)x_<X~wg|WgoP1*8
MRךehqZ/0opɺ=1`[ "nwDSHw#!l(&/64.unxvqF-o{DZ=cQ^z7PG jW-G`rio]?ęq?Wn\8ʺ:`F5)Kchϫe($gK7һPyqE7EM쫲<-ȍ"n[Tg8aJh`
D=Nϛ
Ӹ
Y0i':~ĝdL^7Vn4A{8kOQ=j]hݤ?
hl_V#][[}]Ζrk4/ĵH۠
RӋq0G`YҙF}oQ6vA/B?GGv[
!8.u}`	*tYʣ Kʾh1NCUi]ӗMަjf_K(6<~r)<X"8!x%r
I|>g%|i@IiӃoI_ߜ]<v`z^]*	$kw}МF!㎢Y;ðtG#?M??Q?DdkY7TAhw\kMUwuo1^5i6E4|zp.w=#4gd|J
!PA-Ir+q2BR&!F37͎Fiu<R"!pnKdjs}¦ <a	BA|B"]Av˅z5ޮtdt*2Zd?֓\E"6E/6+v(^ xg~"pt>up1U%hZ=z}8a4=@M20gx]*JXO܌?L>	VlUT3$%:>3/{&¤SJ4aꭗ4Y/	hdKd/9_'o&'~9}{U\ȡ NMfI`Uv./)CR"=? <4x@1\U }
pZ;Y<NKT4i4K2d\]ܝN4)gcx)P\{2mD{4I5Ktgٳx%zrsyv	/\ ?Ea	kq6
_{ӷ晑w8xir~IꀹBN|]K	C1LٻՃu]m7]s @{)LK|NՄFI'`}r{yr}՝R7@jڲ2[(oTeb"!osS8:pf@\r6 \Όfk6P\2t{`_5wQ}=.
Tsril`q2bȮ#䨕y!J҄"YzOOV>قjb'uJ٤M88T("Akh-)RIobB-!$͎0>Գ=m7!TQ7uhLwMcu.0wn4)t
>F*KHhŊ27GPǾ*^*6#i 
9:π <gBcWtZz#S,RcV4}|-tÔY # 
#ȆBa){G<$rҽ$'o	se\f/I[n 	.0a\MRwKYv`$a2$Gv0°2t;i:QO]i$f`jKMM I\hqy_w,-ߙ$}"캈DOe
n]1PW;*rQ
JGRw
K^}Qn_Q'!郖%Ǜ˭ZEr]}(*\{)Sҽ7XfD=_šW&[|_dk_^ZWӇf8ݫֿg	/>9R^wT}CV(y!ٶ*l!k
O)b(&iW'5hsQn E h۳vgdr:L]BP{q$nO_L@w1z>+jsiR$Ph%ܤ5/ċcJD7}L8"v#x|#'Oh?Z;qnцhD5j-WcMX)p,`O7<>?N9ak_hu<JÌ#ϙ>+*b	83Òk ʲ!n&`sJġBcV}q
OI? Sy:m;x4W`.0(sۨʓEdg!XnZz|6_
sEd5WG?/2|Dy`Lh<THUϡE<k$zQjt+GM*}P=BK<U
0s<`k
iǃ^{D{ҽe625:Xdԕ
l+Lnbv<)9h uD9fp#ƕ
0xUQmQLy/NNm7cLXl{Dc
kb_>@D3iw9>!n[ӹ،ӻ_\(8訨ё+7dl;_j|?-[-EOz5^"*R6.XV>"NTc2V<C
	X8&xkX|EftޝI$
RVFiNW(_,N$f Z<7Lc+"w;6wO?%\c7Q4X)N e/qfZĢ
 &{Lh`,^CO\]8C_1K䖲F1 3"JQD-,1/HJLbse[br36=PmX"lZL˾=ޝk_a>PƎ,c9B2Nζ!a_b>(ce0!2qn
.bBcy}!e;$3
mέh:ЏI^U\^yYgwiy3p$Snm"LDd2b1
#l"]O.=QmhᓤҪ>ًEN!n[Hx0"D4󲌘N=&07zrKޮnIaO}\%Шab^ NWwx%0Xu

Ǭ},s~u丽

ݛMT ,&6_5uy#ZuCӁ
ߛNAFNYE?T[  tn$SRɑ۝w2lmz a­jʂaYpfx~oѷ
%h0aYo Wzo^mAKcgnh0vg:H> -
n4^<lQFaڋn~ZTU{Õ%٣0-UuQ5z[9(NAF:ؘ||$SLEQJ5P
2{;+LIpwF
H)'@`%7HNnxg6HK"^d >o6C:~oG%(ceAeWӭ?Kn25
۝v<G($uaa7po"/0FMݺ/*'ܙ= 	HFe-&0N2
Wk
D}_] |x&4ͣbO,yXM"}􋍃y!ΚWM(*I*&tj`~`􇣠3i?Rq׮ܨ3_ d2T`+F{۸]u=%j `xab{\o^3HHCnn>_>\%Nyt0^~N=i2
dԃ2/̍ߙƲع;AXlH-b}	3=/Zji/bJ_ٌm0V0&Wa0tNrD%)[yKO`:^4Fn/I?άo[T^Q0g*fMgIw0v0

D{=5nk
Km'~ݥOwYt$4쒧r^"+ф%j?W 	'Tr;y,q!\ކtҐÓz9oȏ6eKj͹
('B1|snՏEj!
-az|BI4}$4Z_*-f~;U鳶
N1]@]e(;<YUHMD

ȴH*,K)$F"U&Uf*		Kaު/B9O*#~$_d˨RyN
#Z٤lx?ʦꂵGrm?;a/8uː.u'UiζNCa)`"Oyj*dqKfB
9+E@%Ŗ'חKKCvw3x^z%1R=_҆MdQV&V	4ڵ#QP5Lpx*A5%ݦY7lp!QjS7,jH`TTWh
!g=/g
l@Wd|ݧIk4'a	k
Mb{|6pKnVbD[尪GXH?ҷ' #fݻ,6|6cn+b`@\+pm蠠}?+<{Qfi*tV{8fp/LGҜ9+;8D̏'Tkn79\|o9˪H;4x,;摨甇,ލݳ~;X-Bd6FN"Nw9ë{ܝA9E
#JCU	"XCR_gXI,Tcb!.ud5Ģ-C;.;9?wM"06D*k*aw)~s#Z19Q+ozn.,vFoߏzI{:z~鵡vGھz{-:r?C3*ƌި{$FN?	x8%b"4}IM!Irǎņ ?
EĸD5M 9o~.uW;CJj~䝝uk8Ԑ{̏QG~n?GQvI񴛴;-A7H(:0á~KbI{ЎLBN
&~Asf[~1;@[|L+p`:x?j+QEFDtFoO=0!$ѠtAFat,۝N5Nð?A<jQ7Rf
buzjzU3EP木<6,Ej	]0V7s~vo %mͤ Fhyn]p@ b䛨!v !8+WsǱ})q斓TU8L LdەCޑȘIi6ǂQҰCӐJI0(;\wVNwP;{s;_Ըbr\گ1o
z{)dX	Zw'Re@	 +!5)j
:} .u$6iZ3&,M[3EggJ&$d0"h҂W.!zNC!f4
~:3OY@f=xS%j}W`Ԁ7ٯКTdq!BX6?;D*y
b5JDt6Aj߁k<<6̤O/α
qSr͏uk
!U<NaMd
N9M5%oyx:=ḫ`xًtOh]o|g;qy𬑁!t
Y3pV:bXU_,ZrC!`xrsQ-њv_qI sF
@GZK)ya5l3@
lBN%`;%0?ijK}n)ĭ"1ywzn jC39ڴ㕦M) ;m%yPF(;9}ػk_m*X"2t/Vi|&lZt*g
.snPPU,"z~o8Md4jOͺ4atAbP*8äh%*ZJnv_y`Kʱ
M?w8Z|G6KXN3L#-WFP07NAȱzE*i:J&1H4EIdfmHDvp"Sy
j{4'.΄`3xnG~7vA=i4%g2z,gvI7&`D3u Ga*[fm9a=nߴ[Ydk,cڛvp2iz93NQү;{K1[|}jQ_#DR`IhP)9v^K;_P{ẑ
]e+pD4B[!5lza ḣъ֏O_VlA"57ڮ?1+N$dyk[WwCd"=1b>_صwQhXCleȿYP k7r[nϪ0*{qadDg޿92.mjL&/p.j`h'DuZ|@n(P텐sҬ !i!A	 ȩSZb0k<6S?|}hk!<EeUҴۙ(,}"ڪ6ZZÂg!a>kkYL-1М0dDvMo`dLJ8.H,"-*|v;f~4Ep4Gv2;A$}n(tm}?Hiw8LNn{aQaY>xzU#a):[4V,Nhڴ*lz)3#uK0^Koie)ԵOh$Zut:IYg+`!%mK/\H'R#/VU0e8jݩDEZ!;fs35m}zejxH+
c^hcv .(i̔B%pXW5e@F3NodxE5^&ZLΌ0>P_&(=d;BՂ$R+>#1ïiXE#ߪIϪ<DיtGkŦϷc }7 !։(')
Tk-o؝~;6pDm"1Tulam-Ͷ~-M{aIQWN^ &8QhyI?{ޠ$ǰwԏ;i?w-nr;WvF8$sc?O3,0iؐt,^C4xdr,fʃӝ@EE:q\X'AޭuM"xv0x^(	f?50}&Mgd'Ѱ Jj<Hҭ]LfR+OONO~9dnbqeWzf%,iL[[.q nkzY<2*Ґ|6Eu6BE1{HqڶC&J<=at_>^"9 :J99{<p9WnG${
gѢEG{ݠ+ u<?|%p)b#d(ʦ`WK
`ôXRtx#N¹m_WB7*\4% )\ B>HRtV! ~nmPDRqGUnS@E"AfUN_kH `BZ~\T96ӽ:VRxY٦U4
`ݗlGg~)~w$`ˎ:&[$&ixzޠS*h.h;KEM	Lv\kdӌ1J@$	,9{hEt:j*#%=gwgw`-kp՘)+AJG9e?=H6s_UPПY{C㖑tqR:LSg`r8a_^ݽausn aX;Fģ$jp4($QmX`Iza<HA8{NYԎs9h&z!S5m)ж!i
E{@tVU0okRvwM06'9|raHKRv8qƿxc!
˺n1@(@M$:taT$>9bdRO@~\ Yc.>Ey-b&otM"j:
4$g_䆺35MpzZ:{/4+rSC/1KV`uL6a0FK(ީ=%%si(2BXxH%A-i H= (llR=$Q1vį&Fp8u0 ߰NNcCb8{ X?{CFѫa3JvM{}Zڔٰ?lϐ[!-Dxߔu^Red=YݥGD_q3a,L׎GAܚHh
ujB;Wml4IߋG"﷡#oMhGaGQ(T=M}/A3_O߬AzK8T\Ѥɡ c}5qx4PB.#G?^]0,`ĠRWVB%QӤX;NKZmq#0+W
om_@.Љgp\[TػɞHϓ.!#E\2j5fJͥVTn:}>ѧ9G_^3C.zR`ZeBsK=lܭ§<Ar _3Qno,nǸ]dZz7`g0CR9ă$5m'Z\=zr}x)L?{s'4+vN_D_>Ϧ3TdZ_]O.S`]2`}jB)T)VAͷ/|X/ +OqP&S=Q8wKukv
y
7yKtg]r-Z@X2RjT{\%0<a' 鷌0c%FRwآ5|L`M 6<O&ӋpvRFɚ0pbR\W<SX"HQA9x	9  MjŰ!H6dh3ly" dB!64F[[#=^
%1'!q}svqrwh?4"&莥Bv2
 5^*.FqJ).Mɥs rvn-tQQ)
!)20)7}Qo1_U@W\DJϜ)ek+@Җφ-PiO1d|	x߇GCa-Fզ%x%Ьl!+,,&,KEa։"(L7ҁIc<'@<ҶLHlA7:UdpN07cj92^HC/D3IcZ'T1u}9V]Nn.(O?krJPvb	>MU}%┱VCUn/YR?IJ#&B6$_hnapb& ¦XtyDNd@`*`h|DfH?W$FTUpsB6IzxЉbװj4,ˇczK#^9 _3j?+WWi2Dݮ:Vuo@̔0vTJҗ:f陟$Q:N啾	/L"ۮ¡eɴ
 'Cߏ m~w4H4ꂀogǃ0Mn#7ߥ3PWKQtYHd;GAޤIa1e{Cv+܏[
avW0* Vkl!:{}Ƥ36' чMg8ՉH^໢v~:U[]܋b۴]`j<}NՉ:q?';
WTTS~>Zzol6!63ϲ	Lz\O\8I9jiIJ)rUne"r<F2]޷i9;D5R73M_NIKQ4ʏi"[e+JbOŲ EM(c̘,ulu2
#QM/#}==Q&?xPa,))5)9<Rrv3Dd496Lmm"{5V߭^gcx~+oN
B
Td_ӽ2Z 
Ծ~L{j7QfUM^F"+Yk5^`kE!梪|?\*\K&..	wh$c:G]Mf]+RW8sv5|n699kZލ2aAR·%rԦ3PKuEѼ0d5u5ѼMܰS:e,bMJrXϳu
ІO3>Ow[E8>T#X0CP
""MZ&
#Ah!U6W@>YSO
pmj,@ϵ6?䆤+
6?b)H1A b/U',*t	o^jQ 3*K
5%Yhe%S>U˲w _oO~>3$&|w%PYn V`
Qo$$h¸3gQWMhQ0
 8R_4`gL7,tHkt=7
]w_YC쫧gyT!;HVF3VL<hsDcKtl7B5]CsNRO7.xGn]3jPEY`7>1qS.2{MJ.ܝԝG/W{}3TgJHYG	r\:"*T6<H@lp:m·_M hDpj0̣
{8j[?ɜ
ޭhM2^i[T}Utb?
0j'i7
~П~7&aXLΫ\,t~Q{֋a?ޠ=0C;@j%5>1V_9A{ ^SUlVqY*|OBA)xfJuuv0 a6?a(N?uj;N/H%[FF0IR<&A'g`
B
&3Z
MHWu)/+2_S$24ԗb3(p"Q~VI&7dXm2
_!Ho}Һ# ɸԻ%"%+v	{@VԨ&"-HsThQw/r_7H]_"@+3
t^m$:xƠ~c8PekZY%a䩩ItRf2Kf;7:+TEByP;esl0Aw:8N2uʚ
v6ۃN:ʻm=
ǳpګ}v{M{`=O:%ӾzթU;פm-bEQ$/	r;.}uBQ!UFA;zHU2 _}ީaz-DDQokpwo4f0m^DPFzu^ƈ
i;
C8n~kyޯ,q%jm{O*{.!`i/<ޥrAڽGEY0P~4n^<;q4$h+m:شr~OEQi
ntFXkOA.Fk]=Uۑ39eS.dݻ f4?BG[!V$j>z'I['NpL>_B\ zvX#U-۟uT,`p䅝`{I7; 	{A_Mv%a{7`
ߊT4i0Q4Jᴿ2_5w̦_ۃI)SI?z&_畨*|c6޹ĝ
.|7q"p `c2sܒ@ʏMQU!tcB
R`YY`ي{vR XJ
!CTDInaB<X,TʰZ$@$t'lĬQ8Ȧ;cq.""KHzA~P>e_Jb|dj :&MXSܤ"Ee8hcH.CX/,CH?z}d;t2f(ɭH*&m7X٬5U=/N~⃩lu0'g<'GZX/AGTu|~ZZ6xd!\ȃ0*Ry/oW)os:c/lxyr?U%W v3[2&Bl0/݅w嫥nm`H!n,ENNca&^4f~8PALwn2&a^wVN}0;Io8NUXWڈ8quIkpБkR/󫫟On>h`qaoթ EqLNO83gFT^+b.\fG:2-v|Vy9N,}J:7xnQ;Gy0K@9|ƣe<\)TՆ$
<`,Y*,&?UVOv~JHpЏ)"k'.&Hہ3y1ֲ=
]|9HneE~.\Lyjˢ~Gک(r;?-"+)z>'mSHbN?.(ȱYOD(`zx%fq[4>q;@HwӼY;l}YZjCIG	tb|yuX1Ս΀lgfiTڿF;cO P9UXTLQ~y}JMj'2k2՘%Ei!s[{\/"[gG60FdǏ~đ|NukBo|_am[JW>8HqifKD^k90h	
pRE-=g>88!ӏ	^ۅjEl'	0Z:VvzK+0Qq=e6=j?jknK`R{Ňu.{PPxv>&Q$B?ݖˤeG6X LRz{Vup5{ N)PZGS !DBr-' Wj\	Mox.Һ)LhU݋j$?%Wez1aH[˟ԣ[q$axzo7v4`@X/+HI	,%
51y(	frwoVf7}tfzU˧U
E*n[_:W*<޲	ْ T0{!ySⳙ,1p(T5p{^2,ȄfM-fmjzOcڣRP|m|t2@w)-n?fGqIV0X8nqʒ9McaK(:A7ԭ<V-㋫''j0.ƌOIv]+UVwCm?uݽ"
{T1sF%(Z/a`m;s~PORoK!hԢW*R){"V336&q^Vвrvӆ6?+h?}&!ǚ0="?ᔲVj* *Gh7d$^7{jY:mF0Q=瘱
}FXlHoULt3H_`bZ %jfbV> `{NE\,1#xjvq6+d
Xqw~<$x>G̦Q:閨 aO
d<+╷<!s+;F_U| efle |<KC<ww,R?H])dQNZLKLwUzRAEp_eԴ'Y=s]G!g?ӕh	kM&ΣiSzũP{˟ut+lZBsMwSi,,ff!iE=Je5\,qAHXqvrٝ.D;; E~i'o6>)ݷoB
71BSYt'$+|U"Rjnų%KBƶrM#{N_ztvYTҦкI0*k~i}4oQqO}f
>c G00=^P|wnryOT~Nm8Q镞ݠ抺~XI}a铬@kz
Hg
R6:PCfyqՊ4&dȬ=m`Mzn>_43:W7صΕ=xX|a{>Z?*+
8T惁rZ(Eq	
๳buIQ̅:ҕSjkWq=`r4Pm_]ISa;6r{YzI+@ܮ%Z^Fei	 d%9Mf?e!PCtu˽h᱓dN	KU" V?a}u
PbL$U	:6kZq?khg]>/1@t蘤C!p.uUhҥVܺ>RI'^a;Lux :,CS͞_}rҤhyYтc;Dʵ%*p7<|~)`U`;Fl_64->êg5rs_X2X̒&3.lx|_FQa-LRTX1rIbRB9흟GD`FCu[Qan<Lsڇ[Gt	6.NiSD9yIkK뜿ѰHPhӓ;o$#*~+VXYi@'5v0}Xjq1[wQCԖ,C˾/

mcGS<%O@zcU5\"P.F۵$j{ԨCy\,<G)B> ^+_!hwMK/hbrhrhRv;C58Q:K8Wi	99Hg 
TfUd=/ X
$,aи<o4;Ks,
LDedU*EuDSaHtAP8 a+/UPzl*\e1+5K0DXj6[qKIsJ9L5>,(.%F嬧F4\iR7_gzr_Eyʭ=F2{T?L|`146p{j;vZ\b{=Hx&2ƈjAa:hkql#~U2@\~xCKD["ЦQ&Y3ت;0α)&E910;mȕ1++K__FS;_ځ:^J۝*|0'4 <,bɩ=Ֆ~M	<[/%U
%Q_!žkxL~c
6^p`ݠO߼	c?tgj@OٹD
5nkTqSϽ6X 5@/.9`XҼ3[ۖb*4	:ڣ'O0{llb-Ïi.\m:EHZ.XC;ELdGc-
XSH	'>mf5[YOo:miپƋ{07cSs0,pg@ؐw>P
X]k5*>
M
W`y#.*@EaWǰ:8m3V!E%j	iXےl,PG7#>M	n仜zU sXw*r?|:sAC6iBzp@D8a&XCx@	9Eҧ113Pl \W= 8k/21qr9?Kɐ~2.d$8V %M5Gx;Iɓ!NMڹ^3)}˒I\=،^/frrSy뛳_NƮc2QEKAz֡4#OXҼKhTG5nX w*8`l F'_NЧkㇳe9:!S4I#wuSi=}sY@N|Y%l&!E&$Wwe@`Jమ['3xǺyCkT͂Ai*7zoOYğa5H!RGOܢ.;pk+HNO
[]`?r
ܲF耙;O$<sQjE]j^}œjD7	.j'xɍ:\b/Q{tYhLh>`2e,\S~"_`YJjM|MVۮiSh*F+hգOc,;%\4Y e-1[
a\ܠ:K&yE&|/CNϿUQۿU`WaYՍi߰~a7@es7eAF_7iڹE]8f6b	'B	$~YoW~hlئĚlOn1hKҮw~]~ߜz{~ޑJnr$sHMaez7Q!łDLJxXk![>C6M!#]Vf֫({.&BqC%*lWX?$2*,V
.4
5഑'(aiPi[̴C(IB>Z/\j`zͶثn}LW)+f ^TSQ(
9X
g){,]֏ʂ-0V	*&	Ң/W~ 0R@J<Suuh{KrEi|UUjE$!";B?Rͳ
<'!РG.(=Y"Rs-Z(2\IۤÔ\uQm.oޥЫe[Wvǅz5`͘..""4Hlyv{yYWzkXox$_aF*bڒ(;F];C7K^()x8q!o1nZHXKr)V6y\.V|p)5mI,4XH#)p(;DцӖ
&`0{`.EєԾ.=bRg$6t=QUx:
85^m'Gk?:sP,ȁv0l	]jfiv$i\{v_GU+3$#MN3;2)LJŉ=LyH8P*8oQ	ZkҁHpR_,e5A2P-Pm}|IvFfUbЊ5#(6џAo5jָcvݜ}4C^\eo=}JwlBm;ءO jSS]hl
ܠ-HolC,Rȼ6T	ygn\;=
MEoQBFw[ʒM7AC7wOp%	(=Ջۋ^A9OoݽK.Wz0=珴!%lPv':q2c{輩E
pe,	reBqAk E^M{hUCӦQDB43Lp{F!I ")^30ǩ*Hsu8 
vj\Ÿ -Vqdܚ"7σ\#JCyt\܌/~ߞm K5Q
ŕ! wEj&}܃d?C[-ez}[mظwNh
.4fCtXQ-*Di
Βa7'=/<1sPѳ٧H;	v,[&SLr,GԦn\VQ}ӹr77w
#a8->?3_w>)^f}P(7%Kjt2%I#RoNs#-Q!35FQG{eՔxe,gHOp, TQK:(EsK4yM8jߍV8=Զ)	 ;j>eD;%gU_-Ibٛ+ֵXҖX,U.X*^7)XM`R˔Y6zy#IK˫9p&I}gHr*45Fr/6~sGF~.NXt$Rk<pLzEoug֫zf<{u8E(D]3گ`{BVzǱUnǷK9^l`.=}w7/Ahru}wvqϓI!) R˄.VBskA8Ut.?K̛] ~55Xՙ"/&YRI\]\ݕlǑCC9%P<_gFV|"ttUrXƍs\[#2_0_ TIVw
4$Ԗ",u|"XfOX(^Yu5ߔ˙ 3Pf]u+lB`- Ԯ'ٷG\Y;F$-a	-xg52L~|EQQd	j@Z.dpHň&x&JJ|]~TT-\:p6>
Տ?b̞~>:qM ǦÎf씖PG`]ohFwi>F|@ױja"gJ ?pl+r4Y|˝|Mx3}/dTGL=+"oO/KW6aʴʗIruY%zSH߄(BQ}8;TZБNR^a'?J?i֫Nu$Ou']OE'C`Su>eG/K֑7A@sīeâ5%( C3	zՄҩЩ0aIg먆/")
{!jrBI
ґMΌ!bM`-sWе2= 
ۣ5Cɬjinj--$^uӛӟ̙I;72.:IxnC-̧!9uQ#X4V_iJV\"FdDׂ6$.VMMl+*$.	2픨c~hܢ

a-Lyf2J$눜,oW% 
UM	MҿYQ;N魲Nh0>"p2J[H2B1^VovRէͧR[DS¿UKEkzlHjvr@;XS	%<etI Eъ A=f	gPHsCE獩nf^N!|fNQ̖̹E|ljؔOg0)J][kb41xE]ÃЬ%jY]\
Zb|~(Y6I,.A1yEn'?h{>eBˌek	A61dɆk+RwXn*K(pRbS mHWK[$\w-FP_޹%,`	TL BATF&A-˦ D%q |~ol%1S+I84x{,IJ @<H W:h\qz#©H `ڇ+U^nV͞ZG6+c!5>DY<)9<]33jb$%wBW6v5|@&lR^/8.)Z?:ި7mNU_]cҭf+ܞj*;z
)c@@&:x+;qlwĮ'ՠ(-gĢH赆ڐ~db<Xi|r[$V>ҽ$x;H^PZ8=u[e<! ЃVS]#4g@ y^Edx	PebMtЛKqF9Ѐjl4ԅÃ'oOo
T=P_e&=ޅΨUmɊ&~=M9D:Gmo7|L`oz@l3:){]D}`Fɛ@ńL2gҬEeG`^}"ҿЏ|ddd/Q e\I g"k&BV#d+hB~^apw9Ыff{SH27|Mê~	ׅh>(xV$~L̏jӌ`_~.QX.S(cv(ph*H0<B(@E	UF-Aa)(~%NKfZ5P3i0Oi*Zuqz!jiߊ2/a),8(brDh[T!	Uk{PA=uk#`5 c<g [@G-QJ1\\!`x#"g2)ͦji9?Ei	v
ߵh#b:{
%pS쫖dYmY9
7C"PbÀ-+ϑA<_1nנK7w7gFØh8٥T%-LS\g#&?uE?$Gێa-
O)޸lYSj;`@{൜BQ{p$z؃l-2M{,/J\0>ln϶=wfkekpHV8g; 	Bp%6jY[K˔Y@9
KO>!X؇6DFODI-x)*<VmpGݎ[04=JA)GC|X=go&nvp3Xt!7dWvg]kfl=%|-9<
7;ZOT`
4//
P
֪tCcƳOԩX"]Z`w9\Kh fv=0λˮc=O6DsZ#yqφە^GSfG)p3蔕} K&iҢ֊Cqp(gQK}~V5Z\Z2׹݃n,lK(63lŞ^_@ 6+^?3$ˈ@'N}H\B
PxpJzXeNj.u56O¡
rK
[
xuwR0Df)*
2=A0c3gK7&H>>U!Bs
XXz 4j fv}~_y.` 4v
_@<OzvV*PڵK_mW7e!/1QP'bhkՃ0J!vEMAJ2Zs	CJzŬL|;Tmdx\&EtHX<hYW]B))UwAjAXq`CA^[WX=yCQdzݡ:hZnf
v:rea_	\I
Tbj+nwFӿCԓR;gRRuJe`U	2+[{zkF>N)d1q4ɗ4=zp9Mx4a>uo6Y{l\gZ}Ve^rZt<I0+.9 {4`$Cėn"MbYw.!k=c))l{5 <\]0S"p]p ~#e3do̘{vyw\m9ЬV9@D7'góOW7#9DWzK[6?RTBOj.:m`bXh!x)\-n@ުq)ee
;>#O=/e˗PO򻦎GY\rC7X!%ז[LA\ێk{{]-~\Ka(Vfg`[-`1tsB6T}2dՊx%tGt/3;H]{8aBb/.E)W~G )ˍĕNq}.@H	0KZkekWX6G^3 >hCwۿBlΫ]9	Cxl,'&7'.&'[fwfꅧYZb|uw76$p	h[x+&
2Y?bւ!
<H/ɓ(ݦIM $./uNkƺQx
ɰr!7
'A@tB'qA
,I[K܌N&H*h%Z
N&jc
!?M]f{[l5f@]c5C؀Щxe GϢn5Ms̄3 8f4^Ȅa!O3!sEP1	#VCfIHhR=UiGYK$#k©t]#B	þY% ^`VrL	)SG$Oa2QCJj_KW8_{~$?$EΔ$|г:*${A2/!.]3xڪn)WBd1
]c2в;>S`Npx 
L2|f<GSQj`<v<O}Wwo˧6.Q9Cneh9_O35QϮ77uH)b6߃ aw6hؐΗfz`Qud΂ZF
;!\`B:=0/t7DLd
&&[	u,YMsRk(|ǠSL(*!BWHnfJ9X|"]*Vt'>ҝ"SWB`7%,cL_*vPXx{}>rDVf]ZxԤQ}<8T:#٤i&FA-S7a9?][́fU7P' A~<֫NnI/4YU=6 ;`\
(^q2[CdN@1ST| `jKܸܖSgb9 T\
l5OGiƻOu|2<վJ=]Ja^KmvsX  Wx/lcƜ$-ҹ[.\^D@"E]OD/CDA<g6VT}4*qQrڵ0Y-8oʘ=8SQ)!!/J 0-~͸:F{2~lq[ؿxf&pqnnk0o3
䞩Zn۰UxWETnhxn=8%0j00Wv]<)~lFyParz~5m|J豹s
 A6sxEGokۗȋFMtiHN)dw(3%ӊeF+!$۝Πw^w0
!αN\^PA\si}j<jv.FkQ@UTR^\D:kqiբ
<X.izxK[etn*!=;W t~m`T!^ӭLm{n!%*3{1M0U=ybTmVJy$d+giZ5e,Pd9Z
.evsהG뇷"UF(5.{+
n0l1yaЃj<rhB7~iJUf4e	Qvᕃ*gLhOST57lBBުܦ׀vZmEm
N 򬂁.)lU,|3&D&L~xW8taCĖPQKo?LƗN.'󫓻JCA7OMpre$%SZ5چ{B.7;[QbX0#}O!չв.?Um-
6 ܲ}Q.AscQfI{sZbr
|u;=|{˘N;˸vz]כl(KAXHepu,,a᜸ݵ=yuSa@%&UYʲ`FM5DBpm385,|)]X:N#LCGTI3XW g4NKO9;
p'7k6ǓXd"/=aDG'`F+12qss>|a7=m
pZc)MJ,OZ"<犻Ay-]YKWex+j-7RmYwu{朿R0Vx<])B"RCݠ{`)2;#sI*D9Of#<Y	RY׹~wKf>}X1}߷)5`!cM]Kܖb0M6	5j]ŏ*}6N	kRڎuʌ%XԘ;oz=[9]f/=C`3Bp:EMj!<
`n|:`P|,zmVJ*M>~Ce^
:TL
>v޳	bs$H73b!$r)	(Q|_Dt֪W&M &(,Aϗg<c\t益m#預/Z˚3:(pWADfɋHguc>EF+|kBLl\ӱTH&u "\|MqV8Sp/ZuثagXo,MAOљvF8Ek՜T1bqtVOqLK]%
LctZn1@V/8l[Ս7>9Nyo
x-lB7~Ng(BkW1F#9hD&fp0X8EIg$)#=f6<4VM6O{ڃE1C[p[x_"|FO	n'm@PW@Ȧf$bUu8ȝ~YI`ZKW,'Pr|üq (/{o.gmL4!}f?3dX\h#Ss(C]eielhZ=q߅XmˈH@S/T%]t\#&a4ӪxI5܈i$/a0Pfs|8\ X$ϏpM	cQh]k2_EyCCVO'];.\0!-DjL
(\Kt'>v mݚ+5Ji`SHׁcO(v¥\%91Xy"">~?u©*?|&#X7 }鬦\@K52W*`ǽxL!QH(
Nbtƙ5h]n#٪alc`xBRZW\~!
VPݨB1
',8h&Ħ>ЬȟbP}87ӫv^[5STOp0$FdKkt*"r&vɉ?v6*PЩz
gi;!U%n/U?E_
oIBc-x 
rSM\nK9A^E,
 OE\V+8BK
N\+xMp.@vlol?/7M?~ѯDX;%G8TOXw,{	/Z	#,7?}h,AZcKȄ0?`ӛ+ӸZ8=6kmKeesOd.kApzÄJ5@\Gc=4
UzKVy~[F@Jߥ2{@ հnɤ_M3!_LŨҴ[KHL8
{;O8|ivgW_&g}>ds1E`Ln	)h*&h~A0#O̜!,Nk|E5d
i͌XVM)ϙR^`eo6#ڨчH"N
$qt>ARu	<0B-dT)O.oϠfTbf1-UӠ[[09I_87ΞFg&hrmq,I
}$I%PcweibAN+.5Cz*^A#a/_(2YqQhjEٯEϩ[}oށٍK.&}C
z3wT5q4qG{[Zb
'@̠Cfhlp1!:V5@7V*_T$kes=|.*\&<6{(Y+1vY95h&t/ by@*K B̍Z`Vl͓ӳ3õOR-Q}(VuJmmș2HF-t,y=Ku)Ғ=\;QѤ^>BS֞>T8`r58[:R#^(I9G \$;jȖ阠
ΊOVu$"^XUnzX4?A cp,x.MŇǓLqm;O=U{@
/!~t.L?Ղsu<g97yz[rCKt;u3Rr@Jnj{p>Ҟә!kf'"_g_	s?LQqvKPĄGYSҗ!TX *[ڏ
}lgGcmb#̂U/wb`BEݏuu-#EELO$]3=deu~>@xHoEo}ƿj7W׀%i|xSːbV]0p7[Ujb$hzVQ0ME+Zˆ-ԙD!uxAqB[#=>Srua &GBp9^HÅ璚
nQ=%nl|:A,!*IXB)j$MAlk`_z\}c%D.57װUeo
eƢ.V5-1y /jG5%L(ݑ0)-7`J!@8@Rh&MWQ#XE0&M?;$2412ωмrù.Y^ivȨS1v=kT"h:VXum1sCBN0-;1Ki7H <fTgRr52'\ -E7 6trr~rE%}U'lnq
"	b] d> Bld_48^H.("yӔF( DPaߴ	8Źy:ghl8(2ƺj3q*d٣ qn?T jD.;,1>^}zvbA.jV	>`P^,-6?ܯDf՜+
2ݒh7L^(9.J5r;x` Vȫs(,pJܒZ> '<Z;z
=#^bU69D"`(VjY(e9h\Q:,o#>(aGGdQ)CX
Q%L~~-M3~-Pl-bŞq4!JS^T)K\Nm|5ل0dTbk܎ɕfZZ+"^r>E3V޵a8P)0N>|KI.s;!Ks	t1vq.2L!Gb[>1}M,B󡬍ZU7!c3
%QXEĒZ`28<P#aU6mis&]_nIcƆZgSQmRAߒOQc^޸ժ7}\B>j;v~TZ@b@ p_VMbp4|֝!ю(F9f24OXw">O[f#sE7rufzz$Xo}|{*Ii+PP;S,/$zH#5ELL:
dOmr;Gw+R2c0>諅	&g_`e/!"16ttĹFb\r	QxRJ*ًMN])Hl{I~W|ӫ5w*pHUpEH
|cv9oTOckL EDFUBGBȭΖ.fR{(߀vLj!{0(G'$
_ܲYTaN8o&mNF E+*bKm^ C6ӵ4=}q(1[g2L #v-5n>_JʹYzcaq
$$/hqU~WObB'-sog
AO%|x_N>]6IR 36Ɋaz\v{GLjyV6WrePG4OqalGQ O{;[jh0yS
"	C8^^ZWEޙpHB[n++^};?</#+<iVTCm2j|k#M-JsAI,!c8qO;7HdR p]p.W9kTP5k!Y!r*_BaVΐ־$f3pcBKt]Q:k;&"C!D#H}ҦU.[6_=yDm"1gRxGm7J:HFrӱEEn
BYa~-©U#$% AkuHIK
G5'Zj.CD"}I+4RY{xߜrc; 9F*DTKNX4VWVѠN8fse58%1Br5P	ѱ|7ILgqPpAN!(ĬfjX0h5}]''sC0Le~HntS5f԰o2nVf*R !}^GbX)2LJ^K,ƃ.H6p`mE3AofYi_DH4\)dX)Mp6ܵʋm@p	TvbA8=.NUԠTq6.qMghJ&!txޅd¬Kv:4Sݮe3Ct|?u<`=MŻ\8a	6l62
v|y{vwx~&67]H)q*P򴰜{9Z3\eفz+DnKeISfը7N.^ԠT
OL@=$lcXYh:!O]yX{BjeDW?nƟk|Jە`-
*3E|V$a>Dz=/øP5rg4&YBq_(2N_ -0mR]P]y1qfv݇T]$|3xeO
GrV
bzWA+2Vp$ƻnþjwت1SV?Ht8!2!bTD*EuFq3|-[rvOrX|9O%.5-BgXjEj3".,b{\cO%ʲezOWDz"mp\lzAxh::5xQ"7=.FOj,#DPuM\kɁO_S.Nd8~-궩inaOԬi;g]n{cQ6noP:ԹHϤ ?C./EYrro,#EF$yH5_٨2]lq`Ap75:M"ߵKG"vKܹwRZe~lB6|8?Ar,!/Y"ϭy]o3Rjf
l`9-,bAsi0|:T	0B4"{BҴz_Tjz4z&{VM(1ajy\
&>i	ՁDdmoNP,qaii0à.d#-|(YN&|_8 ȣW'A^ʔ<$<Hxf@_bQavaQ'ӫ'h6(VB&i.!<m{ck`$P	gW'DIDW||OVKuNâBiiQ)͵^u^JqU3q'-h*谫:͍ܽ3'ta~{wrq]<m!s^VBJLcy&s2==[U?n7DTnblQ%wGҥM
w2Mۙ"C;\\^EqBm1I)x7ct"E=48̈́V5JيX߄8bGEfZ9ܨjED~BՅfT5!Tٙc5?{ggzR.]Acm	x,ITR9I_pާ47	wŇ-E뛋o˱Be>J*[5R
oBsADvqՋ0*.L, .CsKBek(:NX藧<mPa@=eb0M"h<kwU{&W-C02Q<%M2MB0QF\ ΐŠv&js=%'AL)9%жtEj"4łI,*G{"+% f.w9
LكiAOx%\-Ⱥ]	ڼCر9<Af	VVŢ<TY@4tܚB.1F*!3έGʄJM

%i97Dg\ڲa	+L](2Z)F%.4s)f/Xxa$QB'cSy>j,smŗpҡǄ6(bbYMyB9i0OTQұ{pm#z8voONNj2UQVaIz|s}^'af%rB2.pBCHELczj2j>2͓2gBo*
7 P*jZ@O 彂MNCda%G]̀B(BM%Dϳi8׃0W4ߎo~_|$
RfexFF2},aqUtgIl]>/nEbj,xG uSJ@,Uegq#@Aȟbu,4:O;"4O(CIqUz"Q\[b*n*	LI	@_M61;ph ¥WsNzgr`H#WV7p7;QBZ	<91yVI>ؐR^uz͎O#os l8>?$~A8[Llh{4_t=]AIM7Su]pL^@Q!:HsVIR1Ls@2w^(lh
ӹ^EL<2s=gF*{D:cqdJAmblCyEGE^`.8-06ZZ$"iD%#h8/XtQw\(Xؿx0#²E ["7'h2wRQ6=Uiv*}G	ɱpQI'wW7<Nxb-L8ٔ(Scȹ_U,=`ޏT'M;xV!BV%ѫt3E8?-\kqjiDqñ0Zgy"(I]w&DِĢT'C?ex<Zab!A t.xA%?wxޅ%@sHfD:aR?E3 M`Y3LIVJ9hs;O?x{{9< Х[}wYWEihDb@U
Qt\5J!M1` 1YUKE.Pa]c#YPPVpsQwAKmԫ@ϩZιJ"|ʞ
 e[ؓ_QCr?=S<Q$M>W#%U'TІJ73C{BHK$D!c/s=seWݯ^co4@Ky~<*0srLFAFXԲ2G쒗obJ~r,
J4h]<ԢJ&M-c7"E໪;UÖq9z%mA(^_ݞ4G+~K}Adk8F-,/P{-rT!"V3'"s^!MmTCc7@%RCGgoX¢	QF^9rٝth;U%ںt_p#]n[T$GSj.޼Ĩ0G{LNì
#J3f;KTyبط 
?H2whԛ;;\+tLh.(i60݉r6K{.Ez<w>qPV]!N˨{i3^0Kw`_go&g9kfTPDO-كWF)|w쁣hLhk9&pNՈD"צW9,d֠ZM<qNYmZH~P1>FRn7|܀X31|uQ=%ǧ=19f"P&l*":'*u5|j[YpjmUT0|P?uB{c;XNM7)#:j"poҪi6$<ʥMktȪU@F^i쬃Cr=NY}
R{u0OE<Ŭsؚ?ϵkB;WS&Й"iPIVx\M
e`RrwG݂VCU|FpT\$ыaqw RJ܎/
ӓ'?ߖe	P[3(#^2w::<&FC.ҽԻ`x m+SWě\יC]9iUƃLv#_5P9Jt2ET:,U$5<mXMû!wCe`wٰiۖtzh
B	x6
XxE&KEErI-M>f`+h:L uz tT9	{ixȲ/&9WDېؠu*M״x܉Р&Sj@濫f|}~r:}QP"[79Y3s;N1pq.r>5~)W+*V]U !͡sMǉkS*S
`o4z!ǌ3ڥYFpE?m2>/<N	]EK=Bl$ۖjV -U[B<LsbwH{WF st :)bQxQ]ׅKw!z[Y.g
n2*{!MIo/܇zݑUS{6%.tX[Mzޏ?]KAHjMP&PKێdKD.~}E_Zm$H$"w)@XhDYg55xSք4ϖa )f oN7q҅vIFBPxDFGZ6f{4uE4Aay	,JcKk* ~6HYCNMԿMt>*7JgyqIʔ6VyfvJ-Jeh
я(\r,4΁YZѼބt7Gva!3í\Mk+کC&}6QtxsuGV;djlfi#t?{P/iB إ%'FkZM8X~F>)L%e	)L8|6
#ƪm!Kw-G\h.Rb}=> H:[{nu|e6E7`-j3TatU<^JeF7
fe)(E[`FՋ?drxY$N/Ҭ4FU	$ "P+d),?ʔL<f<][#=x]qK:,cR+p?ghg+$U֐˲Ux=v]:o"k:=zXǛZU1`cu<5$O_ۼtUcȤc;S.";v
Zp:7xSH=VJC<]&ܣv6NSnਢ{
ٵ
@XA8jPB&(M65 8}ݧ33 .u|+Mؤn,,	wft*/`k\X!!Ɨ\?u\Jf皃WS~&DZgNfHrR	_$o>Emu5F*(c2(Imb}sr6J!-!do<,CmBMlA|
e+ 1֑T
\[&=._v3p*yX0ZIz^5p}>?t67ÜmBQHeiz//Mė3;aܮ*V!c<2=PBPd׾3
+⅝jT4WZ=}-)K[uˣ#bR-g
;ZpT2v=<`kد$7*YӫubK{Lq`,?xy7WޔO7}S) אЂm*sXVD nL9URKzJLbI_s9cgX\.?|ip-%S8)a਒\ҫ
58Yn*%'
؁˕2!F49
ZBWr9K҇*sC<%	hnZ}53_HGʠ|~OZ"|W\2`	2Y5S3I\AWbC:t$pqY`;5=ma+9zVFzRڇ6nP,F}bÓp9O1!w8i^R,nEO~x@zuZRz*cEmlI_^@-H	kL^1_Jo>]&α=&8ɱ|
>p8MsO-k|E4MaLK^Ո)*"lB3<<Nsosiy \PA(__F߻}S>HEzXG1G{'{{@ޭ>mh609$=
lARIsҺHL@)9BYHR{?pǆJ8
Дgk$h
5͖.=L%]ę"jy2_GϪ95P LA,ЭZ8ŉ@PUtQ)[@XЫ%>?T ;\aEqmo}% 4P=Vl8cWQEʴB2I#0$5_!oNckW7*Q<yG;)$q"[97(L2w2aasL-c҂TSV*$Dj3$5	>J6hiU+ǙJTL7
z5 U줶h8-JTE"g4j`Y(~U.u~սoZ,U6FRkLs&-Pth"J*9|RL9ނ֤%"SQM@u	|8qw{ A	=7߀-dDT<c-=W{*7kvM*S~![qR%h
Q`3'Us$
	<5ѡT9Q^Q-sDqƔiJP:j0K5OMݺo8-(' 4ݦ=F%*({<Z_x3;,~հtxXߨy?pJ d.Aͫ2H0\̫:== pa+$Q'.L6yUK.\y,K_
ȣ)Qw⮅$CǊ!2s^Mj	Qp9FIezwEnϸ/X3sjrZd)	5 _Xl
aVۻa	pI)f+᎑TD]+Z?>+Y
0eL-E\ژE|uIےErSQAWkP^j哳JmDg!q4	=.~(О,u5gƠbf<
GP
AH2[6_"woHTtTtF)MH聴<	j{Tv9b
~~ޔvKL#VF+Tt-eMeUCUjN~$yuX
8"VS
ޖ{{*7fߣ}ںrhWtlypDɍ?x,KpN3(!50QW(P8Tf^--u96c)gtwH [ZxyR 㭗Ge.lC;PT8>;1yXԠ/qR
n/nJ<Wr0Ǣˤ{xmЪTP4XliUWX6wjB@u|Fgf?$F?}|iF 65y6V/7FTQ=a3MP;IL= JC9=Pt\jhk.L0B{?KO׳$lnAqUȱ-Mv)Lr]pE!'!Y+4.(:_lW,MOP	z`%^#g;pK`HrTjsuL.z-UA?^Ϡ݄%}iN(:I;T\O1e҅դ)cC#A@`o
=Å]]\eQ
V-0tp-BMy]C-DȓԯRO4oI4Xeמl]tHmT\fS/f+Ψ;j撨m&3E)&ˡT}
>6$(m=oaͲP]ЌcQ_<;v;0#{cfVlsM}_א,^>=أ	ytH ot׹R[	Ŵ/m@,UMhֶ7| W2)ȡ} b,7l؄nx14%gd's5gȦ4ܞSwg۟n.>FuUt[VؾEV	V䄁ф.ãj6Na.Z|d<-H!!&x	$m .n'u:ۥ-wA8K
02{)8|fX@oƠ"c'Ix?xm͎hlv+|:6䮫DԼqqd'Nn)DyBAF/Ҡ!tz9UKlO'JxF02
6>s_iȭC`R"4zD#0{!i`g;nϟ~ZXkʵc3C1_	T8mv;=l'vÑbZݨВ@uzBnj?^]q0"!sDGE9VQs(y($UC(تGtm;2xG[ʼ/Sa8&H{RJHK+SNoDͿƶrtK[fgv%=ly˵RV->zRgA'x41(̅ݠQ)'z>u.C?`O39g_#7Le<3ce;|crD pyuGD	yKNw7j`J w;kQj8F0iS)ۼm˳':%"۾i5gE֙%r])/ƙ
 \}8B
~_Ut󴈧%L)A/vE\sUݦ`>KNQ6T޴CsKj>ñ7V䗳O~UR
j3y.yg>O@B]ѰM	)e4`oKݼ
|02߅97$>menm\k֜EYD<.=R!q<=  MRuaGPӺ}d<L =1X%"dmiNkv$ V5CE.vvipBpI3WnWrYsn¥AU&>fP2Z>6S͡
*گBٖJӬ=%4L!Tvՠ^8	ޱ5q9qhFyupB)"x!ǧJlBL2HDpWcT➉BlZKW]FII˻V+5IF!7ƚsDJr

7G 1dN(E?8sl2m68{t4:r#$ceBөY]$XD<hՉ
'(6o8[?`[ :#@)1%jMP
~Dj*[UEl}EN D'ǓQ7$l|q}usn<V\Jl&e
!>$! ܻV9\k%ЫK!vGh%Э
HRV7mlC0eo%jt:
ZV@}V)iW͎.͎^{¿2MGDiuZ3 &뛫ӫsx-mdyHMXffU#ɪj6@	XNJ
*A=AOr&*-n;i'y8\WyܫG]
sg1^$![V-zxf"}(cCaRAb #jFYvd.';*BIWRŜ;+7!ꔞ
٤t2)a<%"TpC=Ɨ?/լE6Vѥ5Ԟ"A碐7+1;Y"o4:
lae,&ǮLUC&h_8rG[3*S.mC=#k4Ȱ MF	m31p̓i=5~X
ͶI)59_uVx )cbʠ`- 7~n(sȉKHYs3&gj,lT$9CŤ""=񎲒QWtR
U7ئ4'얶h-A{  %Q]<*`J$2N?m#imP#0^}x;?:'(WoJ3v
,4얎Q;G`[6,](-9`av5Y,Ģ*R	kxDZ<B!7ź21C!bs)0	$?eYjGTO~,10Qm"C\į }1u^/$nj8썬7y^R3IJ>,jO}U%ZOd!ޑհgrš+Jʘ)DB3qS!PAs=HnfEŅ@J Z"
׌MeB,	-ҔqC@URT͏j}8x՞1QX.N]FW5z=ޞjӟN.?+d	NK5?AiJ̰x""Vp5m\!
1z(>=
x5Ǭ[5fit6tRґ@FG,ZIj@R(bU6Asxf_p0ou&iUkEgPɌ6M05-TV
|ߧ@
H\1yo*Ŷ}4X}ZMy#3V ogH$U# %M=eD@Z=3?C.CZM WO pW"*卡ĦCLWw4jI.e#_ky|aJȪ4Y!~
JX>`̛ᔻ#kvŬyK/;W)"L|vT'`_RaP~Czxװ2M]w@Uuzq_W6cMMeX:hFIAЄIZ<P1ۖ4ەs-]~&oz0_2۸i`gcvKP-e].p*9BS
j|vSO{iQ	'
[mk`OC@4Z*452G #|aFU6"{L8Y@C!)bѼˈwEp2y'ZMgtk,ōDZHLFdeH@h
H	6^bC>$~LBC՜ibdru:g>5T
#0WOa[7[B!mMXK-ߜ:~1b94Lݏ E^4nj^Um^KA&PtʳXJ )ԣT)oUsZxצu( V[B9}\45
TTJ¯O=C*~L|1Ffꔼd-G;Cä,4-~͸$a
P)`[gZM>fAn(D.NJ(4G;X
O<-ѐn=%7dUp 6SSld(˝,+	.%$>e'Xx_DEnCVr$C1dRϳIbZ2V]Rk3KD !Thuٯg8=xOn|]^#;=7Lv
X823m:h͛4׫Djd26:4$fsx$UڮCԜ0S)<XGUd{T -krP5֞j	(xS
/</ǡ&y&-*,Xg-baa)U% OvNN:.8eKß
3bdO0@^	~~{wSp0]
IFc7vAB{WSF/CFl *&.MRĵsv
fWgpGЧ+Dv睬\7ΧĨx?ܻCOKP#kW
.C퓴4{\+<	1]AyItS[S'3ut OPYXF>q~XH(1x4qfiPrYBan9_oSdR`JZSK ,_{OH5;Ι_*m1[z-L͐x"_cǬHSc*4	ጦ@CZˀꙴ \4iI:>isȿ(:t;Psٹ&yu67I
H;WDkULF+o{5+RN&ALr6L\µ
a_NU\^}* l)p^A)&;eqD@%e323:Y60X`eW>y!-ᢸ!?sٹc;Ɖ{QV{WnXE"ra~we"=BಮԐr"8&-lwf^S.դ~G1cJ`frq^W*<mj5,,! qDkEU/#3eK~:QTi5h6\Ul75@8Pۮck2``Bq{]s7c1:s0Q8+- P8Վ@BkvpUp%R~<{±å`\/}#\eTU'vp
|0KXrva'V
m+ATj_0>+pDC
m5ёwUi
Ų78}zuo':N
5{:4S,>;(DXnl4m*.n}&M8ЌgYF\tcfy^@3VfSB(5NN`"ZEMz9006^';X` V=.HI%Ta~hy:^6bQ{C,	3`Yhfb<Zp:҃+r.ݩܩ;n݊q6wNpEx #gEf% u	:n&h	0GqиO]*O*WX\)a/ \,k/!g.c]?3qM6\j<p1e$K?5J[iAӑwwRR <QaZVA'Z-;1e*Hșcp};hehIwAMa<-btСL,BuCm
) cYiUO`(#&ąg Q\UF>"_Y&rjVF7	]2Lүb9nm@45#%DIr:!'Y;]&tj֛cda6vG0,>A4HK"Xk֮uzjF z,(}\
/25{<Z	¶.WfC,*ZHi.tC
a[5(<|Ez;0ѡ1ot$R0aHhn
fB`0:k#V!_Cyҫ,ڍ qJQwqkB_W2%jl;q7O2sP!vn%Yo*ֱd#{{]$gDI7|(rvxXVC D+
԰6h;o~҅Q,@C%?;ajݯ\3 9VKkQpXC;f:!kQY	XDb(J6mݚ]A{ưȏR6. wuy{C84J=
PVЅyH@7eޖS:kTE^z7҄c
֧b3bFT2al4[؄Lne1SIV.UV>F2V~o
$?u eY/%x WD\uy@^ǥҘ~pxTKJI/1XGϕԓ9LI0
,*R`"P8Fq`+O|#
' ,[.0XFQ
A8	I*tMnp8.zJxQlNUbg,-#%CMb7GϥX
KSM6U{i-%zl`֬ᒙ²>{12
6=QO6=Zm\ڀdd<ϖ?67}Py*d|oaPfp >0JX<6u.4;AHMZZUa-.J)@2..J.+%Ƙ&uUkۇ=s#
)isx5;N7|m|흤6îY6Jɇ}ŦSךs pi2ܞgռ\<H`*:Gh]i0Oh5EG,b8 ADD<sIsrul|ֳˬɒbe+*Kq^
9/[ݼ@+8xȐ$g5k .Y?؋_SRZQ
Qae5sւڏt[\)db)cY*8t	*	LXqDe b<
{2E4'R>q
B^4 G+t0iQBRJ`Bqӝ߉O$>ϗgWZ<
_y'?y@7bG;_[5͡jq1n^m˰'wGo8Dކ25E$V\%3`k.Q`X;}{C0-CmbW"Z,pzM.2R绖\ȒKX*XGIIBE%K:'~D#O@+!a3}<ϰ#Dŷa)X|9/c{]qCjB.#$a`]YhOl0R_
;F8;'
Daݖ9\ȏfH!=[q6l
En-je/{,|R F7Pсl%+{aVpv{wvI,I1~/e!utMg9:j+ZRl:Epe:f_fRw wַW]m	I#wvVo<??㱂.[M5N6@[԰\zRt?D9^:_HM}לj߿E
Ȧ|NQrLp<"
E-s
N
'((x9t8նLzQ4o_Sk>p4_Ө?
၂                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          """
Python implementation of the io module.
"""

import os
import abc
import codecs
import errno
import stat
import sys
# Import _thread instead of threading to reduce startup cost
from _thread import allocate_lock as Lock
if sys.platform in {'win32', 'cygwin'}:
    from msvcrt import setmode as _setmode
else:
    _setmode = None

import io
from io import (__all__, SEEK_SET, SEEK_CUR, SEEK_END)

valid_seek_flags = {0, 1, 2}  # Hardwired values
if hasattr(os, 'SEEK_HOLE') :
    valid_seek_flags.add(os.SEEK_HOLE)
    valid_seek_flags.add(os.SEEK_DATA)

# open() uses st_blksize whenever we can
DEFAULT_BUFFER_SIZE = 8 * 1024  # bytes

# NOTE: Base classes defined here are registered with the "official" ABCs
# defined in io.py. We don't use real inheritance though, because we don't want
# to inherit the C implementations.

# Rebind for compatibility
BlockingIOError = BlockingIOError

# Does io.IOBase finalizer log the exception if the close() method fails?
# The exception is ignored silently by default in release build.
_IOBASE_EMITS_UNRAISABLE = (hasattr(sys, "gettotalrefcount") or sys.flags.dev_mode)
# Does open() check its 'errors' argument?
_CHECK_ERRORS = _IOBASE_EMITS_UNRAISABLE


def text_encoding(encoding, stacklevel=2):
    """
    A helper function to choose the text encoding.

    When encoding is not None, this function returns it.
    Otherwise, this function returns the default text encoding
    (i.e. "locale" or "utf-8" depends on UTF-8 mode).

    This function emits an EncodingWarning if *encoding* is None and
    sys.flags.warn_default_encoding is true.

    This can be used in APIs with an encoding=None parameter
    that pass it to TextIOWrapper or open.
    However, please consider using encoding="utf-8" for new APIs.
    """
    if encoding is None:
        if sys.flags.utf8_mode:
            encoding = "utf-8"
        else:
            encoding = "locale"
        if sys.flags.warn_default_encoding:
            import warnings
            warnings.warn("'encoding' argument not specified.",
                          EncodingWarning, stacklevel + 1)
    return encoding


# Wrapper for builtins.open
#
# Trick so that open() won't become a bound method when stored
# as a class variable (as dbm.dumb does).
#
# See init_set_builtins_open() in Python/pylifecycle.c.
@staticmethod
def open(file, mode="r", buffering=-1, encoding=None, errors=None,
         newline=None, closefd=True, opener=None):

    r"""Open file and return a stream.  Raise OSError upon failure.

    file is either a text or byte string giving the name (and the path
    if the file isn't in the current working directory) of the file to
    be opened or an integer file descriptor of the file to be
    wrapped. (If a file descriptor is given, it is closed when the
    returned I/O object is closed, unless closefd is set to False.)

    mode is an optional string that specifies the mode in which the file is
    opened. It defaults to 'r' which means open for reading in text mode. Other
    common values are 'w' for writing (truncating the file if it already
    exists), 'x' for exclusive creation of a new file, and 'a' for appending
    (which on some Unix systems, means that all writes append to the end of the
    file regardless of the current seek position). In text mode, if encoding is
    not specified the encoding used is platform dependent. (For reading and
    writing raw bytes use binary mode and leave encoding unspecified.) The
    available modes are:

    ========= ===============================================================
    Character Meaning
    --------- ---------------------------------------------------------------
    'r'       open for reading (default)
    'w'       open for writing, truncating the file first
    'x'       create a new file and open it for writing
    'a'       open for writing, appending to the end of the file if it exists
    'b'       binary mode
    't'       text mode (default)
    '+'       open a disk file for updating (reading and writing)
    ========= ===============================================================

    The default mode is 'rt' (open for reading text). For binary random
    access, the mode 'w+b' opens and truncates the file to 0 bytes, while
    'r+b' opens the file without truncation. The 'x' mode implies 'w' and
    raises an `FileExistsError` if the file already exists.

    Python distinguishes between files opened in binary and text modes,
    even when the underlying operating system doesn't. Files opened in
    binary mode (appending 'b' to the mode argument) return contents as
    bytes objects without any decoding. In text mode (the default, or when
    't' is appended to the mode argument), the contents of the file are
    returned as strings, the bytes having been first decoded using a
    platform-dependent encoding or using the specified encoding if given.

    buffering is an optional integer used to set the buffering policy.
    Pass 0 to switch buffering off (only allowed in binary mode), 1 to select
    line buffering (only usable in text mode), and an integer > 1 to indicate
    the size of a fixed-size chunk buffer.  When no buffering argument is
    given, the default buffering policy works as follows:

    * Binary files are buffered in fixed-size chunks; the size of the buffer
      is chosen using a heuristic trying to determine the underlying device's
      "block size" and falling back on `io.DEFAULT_BUFFER_SIZE`.
      On many systems, the buffer will typically be 4096 or 8192 bytes long.

    * "Interactive" text files (files for which isatty() returns True)
      use line buffering.  Other text files use the policy described above
      for binary files.

    encoding is the str name of the encoding used to decode or encode the
    file. This should only be used in text mode. The default encoding is
    platform dependent, but any encoding supported by Python can be
    passed.  See the codecs module for the list of supported encodings.

    errors is an optional string that specifies how encoding errors are to
    be handled---this argument should not be used in binary mode. Pass
    'strict' to raise a ValueError exception if there is an encoding error
    (the default of None has the same effect), or pass 'ignore' to ignore
    errors. (Note that ignoring encoding errors can lead to data loss.)
    See the documentation for codecs.register for a list of the permitted
    encoding error strings.

    newline is a string controlling how universal newlines works (it only
    applies to text mode). It can be None, '', '\n', '\r', and '\r\n'.  It works
    as follows:

    * On input, if newline is None, universal newlines mode is
      enabled. Lines in the input can end in '\n', '\r', or '\r\n', and
      these are translated into '\n' before being returned to the
      caller. If it is '', universal newline mode is enabled, but line
      endings are returned to the caller untranslated. If it has any of
      the other legal values, input lines are only terminated by the given
      string, and the line ending is returned to the caller untranslated.

    * On output, if newline is None, any '\n' characters written are
      translated to the system default line separator, os.linesep. If
      newline is '', no translation takes place. If newline is any of the
      other legal values, any '\n' characters written are translated to
      the given string.

    closedfd is a bool. If closefd is False, the underlying file descriptor will
    be kept open when the file is closed. This does not work when a file name is
    given and must be True in that case.

    The newly created file is non-inheritable.

    A custom opener can be used by passing a callable as *opener*. The
    underlying file descriptor for the file object is then obtained by calling
    *opener* with (*file*, *flags*). *opener* must return an open file
    descriptor (passing os.open as *opener* results in functionality similar to
    passing None).

    open() returns a file object whose type depends on the mode, and
    through which the standard file operations such as reading and writing
    are performed. When open() is used to open a file in a text mode ('w',
    'r', 'wt', 'rt', etc.), it returns a TextIOWrapper. When used to open
    a file in a binary mode, the returned class varies: in read binary
    mode, it returns a BufferedReader; in write binary and append binary
    modes, it returns a BufferedWriter, and in read/write mode, it returns
    a BufferedRandom.

    It is also possible to use a string or bytearray as a file for both
    reading and writing. For strings StringIO can be used like a file
    opened in a text mode, and for bytes a BytesIO can be used like a file
    opened in a binary mode.
    """
    if not isinstance(file, int):
        file = os.fspath(file)
    if not isinstance(file, (str, bytes, int)):
        raise TypeError("invalid file: %r" % file)
    if not isinstance(mode, str):
        raise TypeError("invalid mode: %r" % mode)
    if not isinstance(buffering, int):
        raise TypeError("invalid buffering: %r" % buffering)
    if encoding is not None and not isinstance(encoding, str):
        raise TypeError("invalid encoding: %r" % encoding)
    if errors is not None and not isinstance(errors, str):
        raise TypeError("invalid errors: %r" % errors)
    modes = set(mode)
    if modes - set("axrwb+t") or len(mode) > len(modes):
        raise ValueError("invalid mode: %r" % mode)
    creating = "x" in modes
    reading = "r" in modes
    writing = "w" in modes
    appending = "a" in modes
    updating = "+" in modes
    text = "t" in modes
    binary = "b" in modes
    if text and binary:
        raise ValueError("can't have text and binary mode at once")
    if creating + reading + writing + appending > 1:
        raise ValueError("can't have read/write/append mode at once")
    if not (creating or reading or writing or appending):
        raise ValueError("must have exactly one of read/write/append mode")
    if binary and encoding is not None:
        raise ValueError("binary mode doesn't take an encoding argument")
    if binary and errors is not None:
        raise ValueError("binary mode doesn't take an errors argument")
    if binary and newline is not None:
        raise ValueError("binary mode doesn't take a newline argument")
    if binary and buffering == 1:
        import warnings
        warnings.warn("line buffering (buffering=1) isn't supported in binary "
                      "mode, the default buffer size will be used",
                      RuntimeWarning, 2)
    raw = FileIO(file,
                 (creating and "x" or "") +
                 (reading and "r" or "") +
                 (writing and "w" or "") +
                 (appending and "a" or "") +
                 (updating and "+" or ""),
                 closefd, opener=opener)
    result = raw
    try:
        line_buffering = False
        if buffering == 1 or buffering < 0 and raw.isatty():
            buffering = -1
            line_buffering = True
        if buffering < 0:
            buffering = DEFAULT_BUFFER_SIZE
            try:
                bs = os.fstat(raw.fileno()).st_blksize
            except (OSError, AttributeError):
                pass
            else:
                if bs > 1:
                    buffering = bs
        if buffering < 0:
            raise ValueError("invalid buffering size")
        if buffering == 0:
            if binary:
                return result
            raise ValueError("can't have unbuffered text I/O")
        if updating:
            buffer = BufferedRandom(raw, buffering)
        elif creating or writing or appending:
            buffer = BufferedWriter(raw, buffering)
        elif reading:
            buffer = BufferedReader(raw, buffering)
        else:
            raise ValueError("unknown mode: %r" % mode)
        result = buffer
        if binary:
            return result
        encoding = text_encoding(encoding)
        text = TextIOWrapper(buffer, encoding, errors, newline, line_buffering)
        result = text
        text.mode = mode
        return result
    except:
        result.close()
        raise

# Define a default pure-Python implementation for open_code()
# that does not allow hooks. Warn on first use. Defined for tests.
def _open_code_with_warning(path):
    """Opens the provided file with mode ``'rb'``. This function
    should be used when the intent is to treat the contents as
    executable code.

    ``path`` should be an absolute path.

    When supported by the runtime, this function can be hooked
    in order to allow embedders more control over code files.
    This functionality is not supported on the current runtime.
    """
    import warnings
    warnings.warn("_pyio.open_code() may not be using hooks",
                  RuntimeWarning, 2)
    return open(path, "rb")

try:
    open_code = io.open_code
except AttributeError:
    open_code = _open_code_with_warning


def __getattr__(name):
    if name == "OpenWrapper":
        # bpo-43680: Until Python 3.9, _pyio.open was not a static method and
        # builtins.open was set to OpenWrapper to not become a bound method
        # when set to a class variable. _io.open is a built-in function whereas
        # _pyio.open is a Python function. In Python 3.10, _pyio.open() is now
        # a static method, and builtins.open() is now io.open().
        import warnings
        warnings.warn('OpenWrapper is deprecated, use open instead',
                      DeprecationWarning, stacklevel=2)
        global OpenWrapper
        OpenWrapper = open
        return OpenWrapper
    raise AttributeError(f"module {__name__!r} has no attribute {name!r}")


# In normal operation, both `UnsupportedOperation`s should be bound to the
# same object.
try:
    UnsupportedOperation = io.UnsupportedOperation
except AttributeError:
    class UnsupportedOperation(OSError, ValueError):
        pass


class IOBase(metaclass=abc.ABCMeta):

    """The abstract base class for all I/O classes.

    This class provides dummy implementations for many methods that
    derived classes can override selectively; the default implementations
    represent a file that cannot be read, written or seeked.

    Even though IOBase does not declare read or write because
    their signatures will vary, implementations and clients should
    consider those methods part of the interface. Also, implementations
    may raise UnsupportedOperation when operations they do not support are
    called.

    The basic type used for binary data read from or written to a file is
    bytes. Other bytes-like objects are accepted as method arguments too.
    Text I/O classes work with str data.

    Note that calling any method (even inquiries) on a closed stream is
    undefined. Implementations may raise OSError in this case.

    IOBase (and its subclasses) support the iterator protocol, meaning
    that an IOBase object can be iterated over yielding the lines in a
    stream.

    IOBase also supports the :keyword:`with` statement. In this example,
    fp is closed after the suite of the with statement is complete:

    with open('spam.txt', 'r') as fp:
        fp.write('Spam and eggs!')
    """

    ### Internal ###

    def _unsupported(self, name):
        """Internal: raise an OSError exception for unsupported operations."""
        raise UnsupportedOperation("%s.%s() not supported" %
                                   (self.__class__.__name__, name))

    ### Positioning ###

    def seek(self, pos, whence=0):
        """Change stream position.

        Change the stream position to byte offset pos. Argument pos is
        interpreted relative to the position indicated by whence.  Values
        for whence are ints:

        * 0 -- start of stream (the default); offset should be zero or positive
        * 1 -- current stream position; offset may be negative
        * 2 -- end of stream; offset is usually negative
        Some operating systems / file systems could provide additional values.

        Return an int indicating the new absolute position.
        """
        self._unsupported("seek")

    def tell(self):
        """Return an int indicating the current stream position."""
        return self.seek(0, 1)

    def truncate(self, pos=None):
        """Truncate file to size bytes.

        Size defaults to the current IO position as reported by tell().  Return
        the new size.
        """
        self._unsupported("truncate")

    ### Flush and close ###

    def flush(self):
        """Flush write buffers, if applicable.

        This is not implemented for read-only and non-blocking streams.
        """
        self._checkClosed()
        # XXX Should this return the number of bytes written???

    __closed = False

    def close(self):
        """Flush and close the IO object.

        This method has no effect if the file is already closed.
        """
        if not self.__closed:
            try:
                self.flush()
            finally:
                self.__closed = True

    def __del__(self):
        """Destructor.  Calls close()."""
        try:
            closed = self.closed
        except AttributeError:
            # If getting closed fails, then the object is probably
            # in an unusable state, so ignore.
            return

        if closed:
            return

        if _IOBASE_EMITS_UNRAISABLE:
            self.close()
        else:
            # The try/except block is in case this is called at program
            # exit time, when it's possible that globals have already been
            # deleted, and then the close() call might fail.  Since
            # there's nothing we can do about such failures and they annoy
            # the end users, we suppress the traceback.
            try:
                self.close()
            except:
                pass

    ### Inquiries ###

    def seekable(self):
        """Return a bool indicating whether object supports random access.

        If False, seek(), tell() and truncate() will raise OSError.
        This method may need to do a test seek().
        """
        return False

    def _checkSeekable(self, msg=None):
        """Internal: raise UnsupportedOperation if file is not seekable
        """
        if not self.seekable():
            raise UnsupportedOperation("File or stream is not seekable."
                                       if msg is None else msg)

    def readable(self):
        """Return a bool indicating whether object was opened for reading.

        If False, read() will raise OSError.
        """
        return False

    def _checkReadable(self, msg=None):
        """Internal: raise UnsupportedOperation if file is not readable
        """
        if not self.readable():
            raise UnsupportedOperation("File or stream is not readable."
                                       if msg is None else msg)

    def writable(self):
        """Return a bool indicating whether object was opened for writing.

        If False, write() and truncate() will raise OSError.
        """
        return False

    def _checkWritable(self, msg=None):
        """Internal: raise UnsupportedOperation if file is not writable
        """
        if not self.writable():
            raise UnsupportedOperation("File or stream is not writable."
                                       if msg is None else msg)

    @property
    def closed(self):
        """closed: bool.  True iff the file has been closed.

        For backwards compatibility, this is a property, not a predicate.
        """
        return self.__closed

    def _checkClosed(self, msg=None):
        """Internal: raise a ValueError if file is closed
        """
        if self.closed:
            raise ValueError("I/O operation on closed file."
                             if msg is None else msg)

    ### Context manager ###

    def __enter__(self):  # That's a forward reference
        """Context management protocol.  Returns self (an instance of IOBase)."""
        self._checkClosed()
        return self

    def __exit__(self, *args):
        """Context management protocol.  Calls close()"""
        self.close()

    ### Lower-level APIs ###

    # XXX Should these be present even if unimplemented?

    def fileno(self):
        """Returns underlying file descriptor (an int) if one exists.

        An OSError is raised if the IO object does not use a file descriptor.
        """
        self._unsupported("fileno")

    def isatty(self):
        """Return a bool indicating whether this is an 'interactive' stream.

        Return False if it can't be determined.
        """
        self._checkClosed()
        return False

    ### Readline[s] and writelines ###

    def readline(self, size=-1):
        r"""Read and return a line of bytes from the stream.

        If size is specified, at most size bytes will be read.
        Size should be an int.

        The line terminator is always b'\n' for binary files; for text
        files, the newlines argument to open can be used to select the line
        terminator(s) recognized.
        """
        # For backwards compatibility, a (slowish) readline().
        if hasattr(self, "peek"):
            def nreadahead():
                readahead = self.peek(1)
                if not readahead:
                    return 1
                n = (readahead.find(b"\n") + 1) or len(readahead)
                if size >= 0:
                    n = min(n, size)
                return n
        else:
            def nreadahead():
                return 1
        if size is None:
            size = -1
        else:
            try:
                size_index = size.__index__
            except AttributeError:
                raise TypeError(f"{size!r} is not an integer")
            else:
                size = size_index()
        res = bytearray()
        while size < 0 or len(res) < size:
            b = self.read(nreadahead())
            if not b:
                break
            res += b
            if res.endswith(b"\n"):
                break
        return bytes(res)

    def __iter__(self):
        self._checkClosed()
        return self

    def __next__(self):
        line = self.readline()
        if not line:
            raise StopIteration
        return line

    def readlines(self, hint=None):
        """Return a list of lines from the stream.

        hint can be specified to control the number of lines read: no more
        lines will be read if the total size (in bytes/characters) of all
        lines so far exceeds hint.
        """
        if hint is None or hint <= 0:
            return list(self)
        n = 0
        lines = []
        for line in self:
            lines.append(line)
            n += len(line)
            if n >= hint:
                break
        return lines

    def writelines(self, lines):
        """Write a list of lines to the stream.

        Line separators are not added, so it is usual for each of the lines
        provided to have a line separator at the end.
        """
        self._checkClosed()
        for line in lines:
            self.write(line)

io.IOBase.register(IOBase)


class RawIOBase(IOBase):

    """Base class for raw binary I/O."""

    # The read() method is implemented by calling readinto(); derived
    # classes that want to support read() only need to implement
    # readinto() as a primitive operation.  In general, readinto() can be
    # more efficient than read().

    # (It would be tempting to also provide an implementation of
    # readinto() in terms of read(), in case the latter is a more suitable
    # primitive operation, but that would lead to nasty recursion in case
    # a subclass doesn't implement either.)

    def read(self, size=-1):
        """Read and return up to size bytes, where size is an int.

        Returns an empty bytes object on EOF, or None if the object is
        set not to block and has no data to read.
        """
        if size is None:
            size = -1
        if size < 0:
            return self.readall()
        b = bytearray(size.__index__())
        n = self.readinto(b)
        if n is None:
            return None
        del b[n:]
        return bytes(b)

    def readall(self):
        """Read until EOF, using multiple read() call."""
        res = bytearray()
        while True:
            data = self.read(DEFAULT_BUFFER_SIZE)
            if not data:
                break
            res += data
        if res:
            return bytes(res)
        else:
            # b'' or None
            return data

    def readinto(self, b):
        """Read bytes into a pre-allocated bytes-like object b.

        Returns an int representing the number of bytes read (0 for EOF), or
        None if the object is set not to block and has no data to read.
        """
        self._unsupported("readinto")

    def write(self, b):
        """Write the given buffer to the IO stream.

        Returns the number of bytes written, which may be less than the
        length of b in bytes.
        """
        self._unsupported("write")

io.RawIOBase.register(RawIOBase)
from _io import FileIO
RawIOBase.register(FileIO)


class BufferedIOBase(IOBase):

    """Base class for buffered IO objects.

    The main difference with RawIOBase is that the read() method
    supports omitting the size argument, and does not have a default
    implementation that defers to readinto().

    In addition, read(), readinto() and write() may raise
    BlockingIOError if the underlying raw stream is in non-blocking
    mode and not ready; unlike their raw counterparts, they will never
    return None.

    A typical implementation should not inherit from a RawIOBase
    implementation, but wrap one.
    """

    def read(self, size=-1):
        """Read and return up to size bytes, where size is an int.

        If the argument is omitted, None, or negative, reads and
        returns all data until EOF.

        If the argument is positive, and the underlying raw stream is
        not 'interactive', multiple raw reads may be issued to satisfy
        the byte count (unless EOF is reached first).  But for
        interactive raw streams (XXX and for pipes?), at most one raw
        read will be issued, and a short result does not imply that
        EOF is imminent.

        Returns an empty bytes array on EOF.

        Raises BlockingIOError if the underlying raw stream has no
        data at the moment.
        """
        self._unsupported("read")

    def read1(self, size=-1):
        """Read up to size bytes with at most one read() system call,
        where size is an int.
        """
        self._unsupported("read1")

    def readinto(self, b):
        """Read bytes into a pre-allocated bytes-like object b.

        Like read(), this may issue multiple reads to the underlying raw
        stream, unless the latter is 'interactive'.

        Returns an int representing the number of bytes read (0 for EOF).

        Raises BlockingIOError if the underlying raw stream has no
        data at the moment.
        """

        return self._readinto(b, read1=False)

    def readinto1(self, b):
        """Read bytes into buffer *b*, using at most one system call

        Returns an int representing the number of bytes read (0 for EOF).

        Raises BlockingIOError if the underlying raw stream has no
        data at the moment.
        """

        return self._readinto(b, read1=True)

    def _readinto(self, b, read1):
        if not isinstance(b, memoryview):
            b = memoryview(b)
        b = b.cast('B')

        if read1:
            data = self.read1(len(b))
        else:
            data = self.read(len(b))
        n = len(data)

        b[:n] = data

        return n

    def write(self, b):
        """Write the given bytes buffer to the IO stream.

        Return the number of bytes written, which is always the length of b
        in bytes.

        Raises BlockingIOError if the buffer is full and the
        underlying raw stream cannot accept more data at the moment.
        """
        self._unsupported("write")

    def detach(self):
        """
        Separate the underlying raw stream from the buffer and return it.

        After the raw stream has been detached, the buffer is in an unusable
        state.
        """
        self._unsupported("detach")

io.BufferedIOBase.register(BufferedIOBase)


class _BufferedIOMixin(BufferedIOBase):

    """A mixin implementation of BufferedIOBase with an underlying raw stream.

    This passes most requests on to the underlying raw stream.  It
    does *not* provide implementations of read(), readinto() or
    write().
    """

    def __init__(self, raw):
        self._raw = raw

    ### Positioning ###

    def seek(self, pos, whence=0):
        new_position = self.raw.seek(pos, whence)
        if new_position < 0:
            raise OSError("seek() returned an invalid position")
        return new_position

    def tell(self):
        pos = self.raw.tell()
        if pos < 0:
            raise OSError("tell() returned an invalid position")
        return pos

    def truncate(self, pos=None):
        self._checkClosed()
        self._checkWritable()

        # Flush the stream.  We're mixing buffered I/O with lower-level I/O,
        # and a flush may be necessary to synch both views of the current
        # file state.
        self.flush()

        if pos is None:
            pos = self.tell()
        # XXX: Should seek() be used, instead of passing the position
        # XXX  directly to truncate?
        return self.raw.truncate(pos)

    ### Flush and close ###

    def flush(self):
        if self.closed:
            raise ValueError("flush on closed file")
        self.raw.flush()

    def close(self):
        if self.raw is not None and not self.closed:
            try:
                # may raise BlockingIOError or BrokenPipeError etc
                self.flush()
            finally:
                self.raw.close()

    def detach(self):
        if self.raw is None:
            raise ValueError("raw stream already detached")
        self.flush()
        raw = self._raw
        self._raw = None
        return raw

    ### Inquiries ###

    def seekable(self):
        return self.raw.seekable()

    @property
    def raw(self):
        return self._raw

    @property
    def closed(self):
        return self.raw.closed

    @property
    def name(self):
        return self.raw.name

    @property
    def mode(self):
        return self.raw.mode

    def __getstate__(self):
        raise TypeError(f"cannot pickle {self.__class__.__name__!r} object")

    def __repr__(self):
        modname = self.__class__.__module__
        clsname = self.__class__.__qualname__
        try:
            name = self.name
        except AttributeError:
            return "<{}.{}>".format(modname, clsname)
        else:
            return "<{}.{} name={!r}>".format(modname, clsname, name)

    ### Lower-level APIs ###

    def fileno(self):
        return self.raw.fileno()

    def isatty(self):
        return self.raw.isatty()


class BytesIO(BufferedIOBase):

    """Buffered I/O implementation using an in-memory bytes buffer."""

    # Initialize _buffer as soon as possible since it's used by __del__()
    # which calls close()
    _buffer = None

    def __init__(self, initial_bytes=None):
        buf = bytearray()
        if initial_bytes is not None:
            buf += initial_bytes
        self._buffer = buf
        self._pos = 0

    def __getstate__(self):
        if self.closed:
            raise ValueError("__getstate__ on closed file")
        return self.__dict__.copy()

    def getvalue(self):
        """Return the bytes value (contents) of the buffer
        """
        if self.closed:
            raise ValueError("getvalue on closed file")
        return bytes(self._buffer)

    def getbuffer(self):
        """Return a readable and writable view of the buffer.
        """
        if self.closed:
            raise ValueError("getbuffer on closed file")
        return memoryview(self._buffer)

    def close(self):
        if self._buffer is not None:
            self._buffer.clear()
        super().close()

    def read(self, size=-1):
        if self.closed:
            raise ValueError("read from closed file")
        if size is None:
            size = -1
        else:
            try:
                size_index = size.__index__
            except AttributeError:
                raise TypeError(f"{size!r} is not an integer")
            else:
                size = size_index()
        if size < 0:
            size = len(self._buffer)
        if len(self._buffer) <= self._pos:
            return b""
        newpos = min(len(self._buffer), self._pos + size)
        b = self._buffer[self._pos : newpos]
        self._pos = newpos
        return bytes(b)

    def read1(self, size=-1):
        """This is the same as read.
        """
        return self.read(size)

    def write(self, b):
        if self.closed:
            raise ValueError("write to closed file")
        if isinstance(b, str):
            raise TypeError("can't write str to binary stream")
        with memoryview(b) as view:
            n = view.nbytes  # Size of any bytes-like object
        if n == 0:
            return 0
        pos = self._pos
        if pos > len(self._buffer):
            # Inserts null bytes between the current end of the file
            # and the new write position.
            padding = b'\x00' * (pos - len(self._buffer))
            self._buffer += padding
        self._buffer[pos:pos + n] = b
        self._pos += n
        return n

    def seek(self, pos, whence=0):
        if self.closed:
            raise ValueError("seek on closed file")
        try:
            pos_index = pos.__index__
        except AttributeError:
            raise TypeError(f"{pos!r} is not an integer")
        else:
            pos = pos_index()
        if whence == 0:
            if pos < 0:
                raise ValueError("negative seek position %r" % (pos,))
            self._pos = pos
        elif whence == 1:
            self._pos = max(0, self._pos + pos)
        elif whence == 2:
            self._pos = max(0, len(self._buffer) + pos)
        else:
            raise ValueError("unsupported whence value")
        return self._pos

    def tell(self):
        if self.closed:
            raise ValueError("tell on closed file")
        return self._pos

    def truncate(self, pos=None):
        if self.closed:
            raise ValueError("truncate on closed file")
        if pos is None:
            pos = self._pos
        else:
            try:
                pos_index = pos.__index__
            except AttributeError:
                raise TypeError(f"{pos!r} is not an integer")
            else:
                pos = pos_index()
            if pos < 0:
                raise ValueError("negative truncate position %r" % (pos,))
        del self._buffer[pos:]
        return pos

    def readable(self):
        if self.closed:
            raise ValueError("I/O operation on closed file.")
        return True

    def writable(self):
        if self.closed:
            raise ValueError("I/O operation on closed file.")
        return True

    def seekable(self):
        if self.closed:
            raise ValueError("I/O operation on closed file.")
        return True


class BufferedReader(_BufferedIOMixin):

    """BufferedReader(raw[, buffer_size])

    A buffer for a readable, sequential BaseRawIO object.

    The constructor creates a BufferedReader for the given readable raw
    stream and buffer_size. If buffer_size is omitted, DEFAULT_BUFFER_SIZE
    is used.
    """

    def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE):
        """Create a new buffered reader using the given readable raw IO object.
        """
        if not raw.readable():
            raise OSError('"raw" argument must be readable.')

        _BufferedIOMixin.__init__(self, raw)
        if buffer_size <= 0:
            raise ValueError("invalid buffer size")
        self.buffer_size = buffer_size
        self._reset_read_buf()
        self._read_lock = Lock()

    def readable(self):
        return self.raw.readable()

    def _reset_read_buf(self):
        self._read_buf = b""
        self._read_pos = 0

    def read(self, size=None):
        """Read size bytes.

        Returns exactly size bytes of data unless the underlying raw IO
        stream reaches EOF or if the call would block in non-blocking
        mode. If size is negative, read until EOF or until read() would
        block.
        """
        if size is not None and size < -1:
            raise ValueError("invalid number of bytes to read")
        with self._read_lock:
            return self._read_unlocked(size)

    def _read_unlocked(self, n=None):
        nodata_val = b""
        empty_values = (b"", None)
        buf = self._read_buf
        pos = self._read_pos

        # Special case for when the number of bytes to read is unspecified.
        if n is None or n == -1:
            self._reset_read_buf()
            if hasattr(self.raw, 'readall'):
                chunk = self.raw.readall()
                if chunk is None:
                    return buf[pos:] or None
                else:
                    return buf[pos:] + chunk
            chunks = [buf[pos:]]  # Strip the consumed bytes.
            current_size = 0
            while True:
                # Read until EOF or until read() would block.
                chunk = self.raw.read()
                if chunk in empty_values:
                    nodata_val = chunk
                    break
                current_size += len(chunk)
                chunks.append(chunk)
            return b"".join(chunks) or nodata_val

        # The number of bytes to read is specified, return at most n bytes.
        avail = len(buf) - pos  # Length of the available buffered data.
        if n <= avail:
            # Fast path: the data to read is fully buffered.
            self._read_pos += n
            return buf[pos:pos+n]
        # Slow path: read from the stream until enough bytes are read,
        # or until an EOF occurs or until read() would block.
        chunks = [buf[pos:]]
        wanted = max(self.buffer_size, n)
        while avail < n:
            chunk = self.raw.read(wanted)
            if chunk in empty_values:
                nodata_val = chunk
                break
            avail += len(chunk)
            chunks.append(chunk)
        # n is more than avail only when an EOF occurred or when
        # read() would have blocked.
        n = min(n, avail)
        out = b"".join(chunks)
        self._read_buf = out[n:]  # Save the extra data in the buffer.
        self._read_pos = 0
        return out[:n] if out else nodata_val

    def peek(self, size=0):
        """Returns buffered bytes without advancing the position.

        The argument indicates a desired minimal number of bytes; we
        do at most one raw read to satisfy it.  We never return more
        than self.buffer_size.
        """
        with self._read_lock:
            return self._peek_unlocked(size)

    def _peek_unlocked(self, n=0):
        want = min(n, self.buffer_size)
        have = len(self._read_buf) - self._read_pos
        if have < want or have <= 0:
            to_read = self.buffer_size - have
            current = self.raw.read(to_read)
            if current:
                self._read_buf = self._read_buf[self._read_pos:] + current
                self._read_pos = 0
        return self._read_buf[self._read_pos:]

    def read1(self, size=-1):
        """Reads up to size bytes, with at most one read() system call."""
        # Returns up to size bytes.  If at least one byte is buffered, we
        # only return buffered bytes.  Otherwise, we do one raw read.
        if size < 0:
            size = self.buffer_size
        if size == 0:
            return b""
        with self._read_lock:
            self._peek_unlocked(1)
            return self._read_unlocked(
                min(size, len(self._read_buf) - self._read_pos))

    # Implementing readinto() and readinto1() is not strictly necessary (we
    # could rely on the base class that provides an implementation in terms of
    # read() and read1()). We do it anyway to keep the _pyio implementation
    # similar to the io implementation (which implements the methods for
    # performance reasons).
    def _readinto(self, buf, read1):
        """Read data into *buf* with at most one system call."""

        # Need to create a memoryview object of type 'b', otherwise
        # we may not be able to assign bytes to it, and slicing it
        # would create a new object.
        if not isinstance(buf, memoryview):
            buf = memoryview(buf)
        if buf.nbytes == 0:
            return 0
        buf = buf.cast('B')

        written = 0
        with self._read_lock:
            while written < len(buf):

                # First try to read from internal buffer
                avail = min(len(self._read_buf) - self._read_pos, len(buf))
                if avail:
                    buf[written:written+avail] = \
                        self._read_buf[self._read_pos:self._read_pos+avail]
                    self._read_pos += avail
                    written += avail
                    if written == len(buf):
                        break

                # If remaining space in callers buffer is larger than
                # internal buffer, read directly into callers buffer
                if len(buf) - written > self.buffer_size:
                    n = self.raw.readinto(buf[written:])
                    if not n:
                        break # eof
                    written += n

                # Otherwise refill internal buffer - unless we're
                # in read1 mode and already got some data
                elif not (read1 and written):
                    if not self._peek_unlocked(1):
                        break # eof

                # In readinto1 mode, return as soon as we have some data
                if read1 and written:
                    break

        return written

    def tell(self):
        return _BufferedIOMixin.tell(self) - len(self._read_buf) + self._read_pos

    def seek(self, pos, whence=0):
        if whence not in valid_seek_flags:
            raise ValueError("invalid whence value")
        with self._read_lock:
            if whence == 1:
                pos -= len(self._read_buf) - self._read_pos
            pos = _BufferedIOMixin.seek(self, pos, whence)
            self._reset_read_buf()
            return pos

class BufferedWriter(_BufferedIOMixin):

    """A buffer for a writeable sequential RawIO object.

    The constructor creates a BufferedWriter for the given writeable raw
    stream. If the buffer_size is not given, it defaults to
    DEFAULT_BUFFER_SIZE.
    """

    def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE):
        if not raw.writable():
            raise OSError('"raw" argument must be writable.')

        _BufferedIOMixin.__init__(self, raw)
        if buffer_size <= 0:
            raise ValueError("invalid buffer size")
        self.buffer_size = buffer_size
        self._write_buf = bytearray()
        self._write_lock = Lock()

    def writable(self):
        return self.raw.writable()

    def write(self, b):
        if isinstance(b, str):
            raise TypeError("can't write str to binary stream")
        with self._write_lock:
            if self.closed:
                raise ValueError("write to closed file")
            # XXX we can implement some more tricks to try and avoid
            # partial writes
            if len(self._write_buf) > self.buffer_size:
                # We're full, so let's pre-flush the buffer.  (This may
                # raise BlockingIOError with characters_written == 0.)
                self._flush_unlocked()
            before = len(self._write_buf)
            self._write_buf.extend(b)
            written = len(self._write_buf) - before
            if len(self._write_buf) > self.buffer_size:
                try:
                    self._flush_unlocked()
                except BlockingIOError as e:
                    if len(self._write_buf) > self.buffer_size:
                        # We've hit the buffer_size. We have to accept a partial
                        # write and cut back our buffer.
                        overage = len(self._write_buf) - self.buffer_size
                        written -= overage
                        self._write_buf = self._write_buf[:self.buffer_size]
                        raise BlockingIOError(e.errno, e.strerror, written)
            return written

    def truncate(self, pos=None):
        with self._write_lock:
            self._flush_unlocked()
            if pos is None:
                pos = self.raw.tell()
            return self.raw.truncate(pos)

    def flush(self):
        with self._write_lock:
            self._flush_unlocked()

    def _flush_unlocked(self):
        if self.closed:
            raise ValueError("flush on closed file")
        while self._write_buf:
            try:
                n = self.raw.write(self._write_buf)
            except BlockingIOError:
                raise RuntimeError("self.raw should implement RawIOBase: it "
                                   "should not raise BlockingIOError")
            if n is None:
                raise BlockingIOError(
                    errno.EAGAIN,
                    "write could not complete without blocking", 0)
            if n > len(self._write_buf) or n < 0:
                raise OSError("write() returned incorrect number of bytes")
            del self._write_buf[:n]

    def tell(self):
        return _BufferedIOMixin.tell(self) + len(self._write_buf)

    def seek(self, pos, whence=0):
        if whence not in valid_seek_flags:
            raise ValueError("invalid whence value")
        with self._write_lock:
            self._flush_unlocked()
            return _BufferedIOMixin.seek(self, pos, whence)

    def close(self):
        with self._write_lock:
            if self.raw is None or self.closed:
                return
        # We have to release the lock and call self.flush() (which will
        # probably just re-take the lock) in case flush has been overridden in
        # a subclass or the user set self.flush to something. This is the same
        # behavior as the C implementation.
        try:
            # may raise BlockingIOError or BrokenPipeError etc
            self.flush()
        finally:
            with self._write_lock:
                self.raw.close()


class BufferedRWPair(BufferedIOBase):

    """A buffered reader and writer object together.

    A buffered reader object and buffered writer object put together to
    form a sequential IO object that can read and write. This is typically
    used with a socket or two-way pipe.

    reader and writer are RawIOBase objects that are readable and
    writeable respectively. If the buffer_size is omitted it defaults to
    DEFAULT_BUFFER_SIZE.
    """

    # XXX The usefulness of this (compared to having two separate IO
    # objects) is questionable.

    def __init__(self, reader, writer, buffer_size=DEFAULT_BUFFER_SIZE):
        """Constructor.

        The arguments are two RawIO instances.
        """
        if not reader.readable():
            raise OSError('"reader" argument must be readable.')

        if not writer.writable():
            raise OSError('"writer" argument must be writable.')

        self.reader = BufferedReader(reader, buffer_size)
        self.writer = BufferedWriter(writer, buffer_size)

    def read(self, size=-1):
        if size is None:
            size = -1
        return self.reader.read(size)

    def readinto(self, b):
        return self.reader.readinto(b)

    def write(self, b):
        return self.writer.write(b)

    def peek(self, size=0):
        return self.reader.peek(size)

    def read1(self, size=-1):
        return self.reader.read1(size)

    def readinto1(self, b):
        return self.reader.readinto1(b)

    def readable(self):
        return self.reader.readable()

    def writable(self):
        return self.writer.writable()

    def flush(self):
        return self.writer.flush()

    def close(self):
        try:
            self.writer.close()
        finally:
            self.reader.close()

    def isatty(self):
        return self.reader.isatty() or self.writer.isatty()

    @property
    def closed(self):
        return self.writer.closed


class BufferedRandom(BufferedWriter, BufferedReader):

    """A buffered interface to random access streams.

    The constructor creates a reader and writer for a seekable stream,
    raw, given in the first argument. If the buffer_size is omitted it
    defaults to DEFAULT_BUFFER_SIZE.
    """

    def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE):
        raw._checkSeekable()
        BufferedReader.__init__(self, raw, buffer_size)
        BufferedWriter.__init__(self, raw, buffer_size)

    def seek(self, pos, whence=0):
        if whence not in valid_seek_flags:
            raise ValueError("invalid whence value")
        self.flush()
        if self._read_buf:
            # Undo read ahead.
            with self._read_lock:
                self.raw.seek(self._read_pos - len(self._read_buf), 1)
        # First do the raw seek, then empty the read buffer, so that
        # if the raw seek fails, we don't lose buffered data forever.
        pos = self.raw.seek(pos, whence)
        with self._read_lock:
            self._reset_read_buf()
        if pos < 0:
            raise OSError("seek() returned invalid position")
        return pos

    def tell(self):
        if self._write_buf:
            return BufferedWriter.tell(self)
        else:
            return BufferedReader.tell(self)

    def truncate(self, pos=None):
        if pos is None:
            pos = self.tell()
        # Use seek to flush the read buffer.
        return BufferedWriter.truncate(self, pos)

    def read(self, size=None):
        if size is None:
            size = -1
        self.flush()
        return BufferedReader.read(self, size)

    def readinto(self, b):
        self.flush()
        return BufferedReader.readinto(self, b)

    def peek(self, size=0):
        self.flush()
        return BufferedReader.peek(self, size)

    def read1(self, size=-1):
        self.flush()
        return BufferedReader.read1(self, size)

    def readinto1(self, b):
        self.flush()
        return BufferedReader.readinto1(self, b)

    def write(self, b):
        if self._read_buf:
            # Undo readahead
            with self._read_lock:
                self.raw.seek(self._read_pos - len(self._read_buf), 1)
                self._reset_read_buf()
        return BufferedWriter.write(self, b)


class FileIO(RawIOBase):
    _fd = -1
    _created = False
    _readable = False
    _writable = False
    _appending = False
    _seekable = None
    _closefd = True

    def __init__(self, file, mode='r', closefd=True, opener=None):
        """Open a file.  The mode can be 'r' (default), 'w', 'x' or 'a' for reading,
        writing, exclusive creation or appending.  The file will be created if it
        doesn't exist when opened for writing or appending; it will be truncated
        when opened for writing.  A FileExistsError will be raised if it already
        exists when opened for creating. Opening a file for creating implies
        writing so this mode behaves in a similar way to 'w'. Add a '+' to the mode
        to allow simultaneous reading and writing. A custom opener can be used by
        passing a callable as *opener*. The underlying file descriptor for the file
        object is then obtained by calling opener with (*name*, *flags*).
        *opener* must return an open file descriptor (passing os.open as *opener*
        results in functionality similar to passing None).
        """
        if self._fd >= 0:
            # Have to close the existing file first.
            try:
                if self._closefd:
                    os.close(self._fd)
            finally:
                self._fd = -1

        if isinstance(file, float):
            raise TypeError('integer argument expected, got float')
        if isinstance(file, int):
            fd = file
            if fd < 0:
                raise ValueError('negative file descriptor')
        else:
            fd = -1

        if not isinstance(mode, str):
            raise TypeError('invalid mode: %s' % (mode,))
        if not set(mode) <= set('xrwab+'):
            raise ValueError('invalid mode: %s' % (mode,))
        if sum(c in 'rwax' for c in mode) != 1 or mode.count('+') > 1:
            raise ValueError('Must have exactly one of create/read/write/append '
                             'mode and at most one plus')

        if 'x' in mode:
            self._created = True
            self._writable = True
            flags = os.O_EXCL | os.O_CREAT
        elif 'r' in mode:
            self._readable = True
            flags = 0
        elif 'w' in mode:
            self._writable = True
            flags = os.O_CREAT | os.O_TRUNC
        elif 'a' in mode:
            self._writable = True
            self._appending = True
            flags = os.O_APPEND | os.O_CREAT

        if '+' in mode:
            self._readable = True
            self._writable = True

        if self._readable and self._writable:
            flags |= os.O_RDWR
        elif self._readable:
            flags |= os.O_RDONLY
        else:
            flags |= os.O_WRONLY

        flags |= getattr(os, 'O_BINARY', 0)

        noinherit_flag = (getattr(os, 'O_NOINHERIT', 0) or
                          getattr(os, 'O_CLOEXEC', 0))
        flags |= noinherit_flag

        owned_fd = None
        try:
            if fd < 0:
                if not closefd:
                    raise ValueError('Cannot use closefd=False with file name')
                if opener is None:
                    fd = os.open(file, flags, 0o666)
                else:
                    fd = opener(file, flags)
                    if not isinstance(fd, int):
                        raise TypeError('expected integer from opener')
                    if fd < 0:
                        raise OSError('Negative file descriptor')
                owned_fd = fd
                if not noinherit_flag:
                    os.set_inheritable(fd, False)

            self._closefd = closefd
            fdfstat = os.fstat(fd)
            try:
                if stat.S_ISDIR(fdfstat.st_mode):
                    raise IsADirectoryError(errno.EISDIR,
                                            os.strerror(errno.EISDIR), file)
            except AttributeError:
                # Ignore the AttributeError if stat.S_ISDIR or errno.EISDIR
                # don't exist.
                pass
            self._blksize = getattr(fdfstat, 'st_blksize', 0)
            if self._blksize <= 1:
                self._blksize = DEFAULT_BUFFER_SIZE

            if _setmode:
                # don't translate newlines (\r\n <=> \n)
                _setmode(fd, os.O_BINARY)

            self.name = file
            if self._appending:
                # For consistent behaviour, we explicitly seek to the
                # end of file (otherwise, it might be done only on the
                # first write()).
                try:
                    os.lseek(fd, 0, SEEK_END)
                except OSError as e:
                    if e.errno != errno.ESPIPE:
                        raise
        except:
            if owned_fd is not None:
                os.close(owned_fd)
            raise
        self._fd = fd

    def __del__(self):
        if self._fd >= 0 and self._closefd and not self.closed:
            import warnings
            warnings.warn('unclosed file %r' % (self,), ResourceWarning,
                          stacklevel=2, source=self)
            self.close()

    def __getstate__(self):
        raise TypeError(f"cannot pickle {self.__class__.__name__!r} object")

    def __repr__(self):
        class_name = '%s.%s' % (self.__class__.__module__,
                                self.__class__.__qualname__)
        if self.closed:
            return '<%s [closed]>' % class_name
        try:
            name = self.name
        except AttributeError:
            return ('<%s fd=%d mode=%r closefd=%r>' %
                    (class_name, self._fd, self.mode, self._closefd))
        else:
            return ('<%s name=%r mode=%r closefd=%r>' %
                    (class_name, name, self.mode, self._closefd))

    def _checkReadable(self):
        if not self._readable:
            raise UnsupportedOperation('File not open for reading')

    def _checkWritable(self, msg=None):
        if not self._writable:
            raise UnsupportedOperation('File not open for writing')

    def read(self, size=None):
        """Read at most size bytes, returned as bytes.

        Only makes one system call, so less data may be returned than requested
        In non-blocking mode, returns None if no data is available.
        Return an empty bytes object at EOF.
        """
        self._checkClosed()
        self._checkReadable()
        if size is None or size < 0:
            return self.readall()
        try:
            return os.read(self._fd, size)
        except BlockingIOError:
            return None

    def readall(self):
        """Read all data from the file, returned as bytes.

        In non-blocking mode, returns as much as is immediately available,
        or None if no data is available.  Return an empty bytes object at EOF.
        """
        self._checkClosed()
        self._checkReadable()
        bufsize = DEFAULT_BUFFER_SIZE
        try:
            pos = os.lseek(self._fd, 0, SEEK_CUR)
            end = os.fstat(self._fd).st_size
            if end >= pos:
                bufsize = end - pos + 1
        except OSError:
            pass

        result = bytearray()
        while True:
            if len(result) >= bufsize:
                bufsize = len(result)
                bufsize += max(bufsize, DEFAULT_BUFFER_SIZE)
            n = bufsize - len(result)
            try:
                chunk = os.read(self._fd, n)
            except BlockingIOError:
                if result:
                    break
                return None
            if not chunk: # reached the end of the file
                break
            result += chunk

        return bytes(result)

    def readinto(self, b):
        """Same as RawIOBase.readinto()."""
        m = memoryview(b).cast('B')
        data = self.read(len(m))
        n = len(data)
        m[:n] = data
        return n

    def write(self, b):
        """Write bytes b to file, return number written.

        Only makes one system call, so not all of the data may be written.
        The number of bytes actually written is returned.  In non-blocking mode,
        returns None if the write would block.
        """
        self._checkClosed()
        self._checkWritable()
        try:
            return os.write(self._fd, b)
        except BlockingIOError:
            return None

    def seek(self, pos, whence=SEEK_SET):
        """Move to new file position.

        Argument offset is a byte count.  Optional argument whence defaults to
        SEEK_SET or 0 (offset from start of file, offset should be >= 0); other values
        are SEEK_CUR or 1 (move relative to current position, positive or negative),
        and SEEK_END or 2 (move relative to end of file, usually negative, although
        many platforms allow seeking beyond the end of a file).

        Note that not all file objects are seekable.
        """
        if isinstance(pos, float):
            raise TypeError('an integer is required')
        self._checkClosed()
        return os.lseek(self._fd, pos, whence)

    def tell(self):
        """tell() -> int.  Current file position.

        Can raise OSError for non seekable files."""
        self._checkClosed()
        return os.lseek(self._fd, 0, SEEK_CUR)

    def truncate(self, size=None):
        """Truncate the file to at most size bytes.

        Size defaults to the current file position, as returned by tell().
        The current file position is changed to the value of size.
        """
        self._checkClosed()
        self._checkWritable()
        if size is None:
            size = self.tell()
        os.ftruncate(self._fd, size)
        return size

    def close(self):
        """Close the file.

        A closed file cannot be used for further I/O operations.  close() may be
        called more than once without error.
        """
        if not self.closed:
            try:
                if self._closefd:
                    os.close(self._fd)
            finally:
                super().close()

    def seekable(self):
        """True if file supports random-access."""
        self._checkClosed()
        if self._seekable is None:
            try:
                self.tell()
            except OSError:
                self._seekable = False
            else:
                self._seekable = True
        return self._seekable

    def readable(self):
        """True if file was opened in a read mode."""
        self._checkClosed()
        return self._readable

    def writable(self):
        """True if file was opened in a write mode."""
        self._checkClosed()
        return self._writable

    def fileno(self):
        """Return the underlying file descriptor (an integer)."""
        self._checkClosed()
        return self._fd

    def isatty(self):
        """True if the file is connected to a TTY device."""
        self._checkClosed()
        return os.isatty(self._fd)

    @property
    def closefd(self):
        """True if the file descriptor will be closed by close()."""
        return self._closefd

    @property
    def mode(self):
        """String giving the file mode"""
        if self._created:
            if self._readable:
                return 'xb+'
            else:
                return 'xb'
        elif self._appending:
            if self._readable:
                return 'ab+'
            else:
                return 'ab'
        elif self._readable:
            if self._writable:
                return 'rb+'
            else:
                return 'rb'
        else:
            return 'wb'


class TextIOBase(IOBase):

    """Base class for text I/O.

    This class provides a character and line based interface to stream
    I/O.
    """

    def read(self, size=-1):
        """Read at most size characters from stream, where size is an int.

        Read from underlying buffer until we have size characters or we hit EOF.
        If size is negative or omitted, read until EOF.

        Returns a string.
        """
        self._unsupported("read")

    def write(self, s):
        """Write string s to stream and returning an int."""
        self._unsupported("write")

    def truncate(self, pos=None):
        """Truncate size to pos, where pos is an int."""
        self._unsupported("truncate")

    def readline(self):
        """Read until newline or EOF.

        Returns an empty string if EOF is hit immediately.
        """
        self._unsupported("readline")

    def detach(self):
        """
        Separate the underlying buffer from the TextIOBase and return it.

        After the underlying buffer has been detached, the TextIO is in an
        unusable state.
        """
        self._unsupported("detach")

    @property
    def encoding(self):
        """Subclasses should override."""
        return None

    @property
    def newlines(self):
        """Line endings translated so far.

        Only line endings translated during reading are considered.

        Subclasses should override.
        """
        return None

    @property
    def errors(self):
        """Error setting of the decoder or encoder.

        Subclasses should override."""
        return None

io.TextIOBase.register(TextIOBase)


class IncrementalNewlineDecoder(codecs.IncrementalDecoder):
    r"""Codec used when reading a file in universal newlines mode.  It wraps
    another incremental decoder, translating \r\n and \r into \n.  It also
    records the types of newlines encountered.  When used with
    translate=False, it ensures that the newline sequence is returned in
    one piece.
    """
    def __init__(self, decoder, translate, errors='strict'):
        codecs.IncrementalDecoder.__init__(self, errors=errors)
        self.translate = translate
        self.decoder = decoder
        self.seennl = 0
        self.pendingcr = False

    def decode(self, input, final=False):
        # decode input (with the eventual \r from a previous pass)
        if self.decoder is None:
            output = input
        else:
            output = self.decoder.decode(input, final=final)
        if self.pendingcr and (output or final):
            output = "\r" + output
            self.pendingcr = False

        # retain last \r even when not translating data:
        # then readline() is sure to get \r\n in one pass
        if output.endswith("\r") and not final:
            output = output[:-1]
            self.pendingcr = True

        # Record which newlines are read
        crlf = output.count('\r\n')
        cr = output.count('\r') - crlf
        lf = output.count('\n') - crlf
        self.seennl |= (lf and self._LF) | (cr and self._CR) \
                    | (crlf and self._CRLF)

        if self.translate:
            if crlf:
                output = output.replace("\r\n", "\n")
            if cr:
                output = output.replace("\r", "\n")

        return output

    def getstate(self):
        if self.decoder is None:
            buf = b""
            flag = 0
        else:
            buf, flag = self.decoder.getstate()
        flag <<= 1
        if self.pendingcr:
            flag |= 1
        return buf, flag

    def setstate(self, state):
        buf, flag = state
        self.pendingcr = bool(flag & 1)
        if self.decoder is not None:
            self.decoder.setstate((buf, flag >> 1))

    def reset(self):
        self.seennl = 0
        self.pendingcr = False
        if self.decoder is not None:
            self.decoder.reset()

    _LF = 1
    _CR = 2
    _CRLF = 4

    @property
    def newlines(self):
        return (None,
                "\n",
                "\r",
                ("\r", "\n"),
                "\r\n",
                ("\n", "\r\n"),
                ("\r", "\r\n"),
                ("\r", "\n", "\r\n")
               )[self.seennl]


class TextIOWrapper(TextIOBase):

    r"""Character and line based layer over a BufferedIOBase object, buffer.

    encoding gives the name of the encoding that the stream will be
    decoded or encoded with. It defaults to locale.getencoding().

    errors determines the strictness of encoding and decoding (see the
    codecs.register) and defaults to "strict".

    newline can be None, '', '\n', '\r', or '\r\n'.  It controls the
    handling of line endings. If it is None, universal newlines is
    enabled.  With this enabled, on input, the lines endings '\n', '\r',
    or '\r\n' are translated to '\n' before being returned to the
    caller. Conversely, on output, '\n' is translated to the system
    default line separator, os.linesep. If newline is any other of its
    legal values, that newline becomes the newline when the file is read
    and it is returned untranslated. On output, '\n' is converted to the
    newline.

    If line_buffering is True, a call to flush is implied when a call to
    write contains a newline character.
    """

    _CHUNK_SIZE = 2048

    # Initialize _buffer as soon as possible since it's used by __del__()
    # which calls close()
    _buffer = None

    # The write_through argument has no effect here since this
    # implementation always writes through.  The argument is present only
    # so that the signature can match the signature of the C version.
    def __init__(self, buffer, encoding=None, errors=None, newline=None,
                 line_buffering=False, write_through=False):
        self._check_newline(newline)
        encoding = text_encoding(encoding)

        if encoding == "locale":
            encoding = self._get_locale_encoding()

        if not isinstance(encoding, str):
            raise ValueError("invalid encoding: %r" % encoding)

        if not codecs.lookup(encoding)._is_text_encoding:
            msg = ("%r is not a text encoding; "
                   "use codecs.open() to handle arbitrary codecs")
            raise LookupError(msg % encoding)

        if errors is None:
            errors = "strict"
        else:
            if not isinstance(errors, str):
                raise ValueError("invalid errors: %r" % errors)
            if _CHECK_ERRORS:
                codecs.lookup_error(errors)

        self._buffer = buffer
        self._decoded_chars = ''  # buffer for text returned from decoder
        self._decoded_chars_used = 0  # offset into _decoded_chars for read()
        self._snapshot = None  # info for reconstructing decoder state
        self._seekable = self._telling = self.buffer.seekable()
        self._has_read1 = hasattr(self.buffer, 'read1')
        self._configure(encoding, errors, newline,
                        line_buffering, write_through)

    def _check_newline(self, newline):
        if newline is not None and not isinstance(newline, str):
            raise TypeError("illegal newline type: %r" % (type(newline),))
        if newline not in (None, "", "\n", "\r", "\r\n"):
            raise ValueError("illegal newline value: %r" % (newline,))

    def _configure(self, encoding=None, errors=None, newline=None,
                   line_buffering=False, write_through=False):
        self._encoding = encoding
        self._errors = errors
        self._encoder = None
        self._decoder = None
        self._b2cratio = 0.0

        self._readuniversal = not newline
        self._readtranslate = newline is None
        self._readnl = newline
        self._writetranslate = newline != ''
        self._writenl = newline or os.linesep

        self._line_buffering = line_buffering
        self._write_through = write_through

        # don't write a BOM in the middle of a file
        if self._seekable and self.writable():
            position = self.buffer.tell()
            if position != 0:
                try:
                    self._get_encoder().setstate(0)
                except LookupError:
                    # Sometimes the encoder doesn't exist
                    pass

    # self._snapshot is either None, or a tuple (dec_flags, next_input)
    # where dec_flags is the second (integer) item of the decoder state
    # and next_input is the chunk of input bytes that comes next after the
    # snapshot point.  We use this to reconstruct decoder states in tell().

    # Naming convention:
    #   - "bytes_..." for integer variables that count input bytes
    #   - "chars_..." for integer variables that count decoded characters

    def __repr__(self):
        result = "<{}.{}".format(self.__class__.__module__,
                                 self.__class__.__qualname__)
        try:
            name = self.name
        except AttributeError:
            pass
        else:
            result += " name={0!r}".format(name)
        try:
            mode = self.mode
        except AttributeError:
            pass
        else:
            result += " mode={0!r}".format(mode)
        return result + " encoding={0!r}>".format(self.encoding)

    @property
    def encoding(self):
        return self._encoding

    @property
    def errors(self):
        return self._errors

    @property
    def line_buffering(self):
        return self._line_buffering

    @property
    def write_through(self):
        return self._write_through

    @property
    def buffer(self):
        return self._buffer

    def reconfigure(self, *,
                    encoding=None, errors=None, newline=Ellipsis,
                    line_buffering=None, write_through=None):
        """Reconfigure the text stream with new parameters.

        This also flushes the stream.
        """
        if (self._decoder is not None
                and (encoding is not None or errors is not None
                     or newline is not Ellipsis)):
            raise UnsupportedOperation(
                "It is not possible to set the encoding or newline of stream "
                "after the first read")

        if errors is None:
            if encoding is None:
                errors = self._errors
            else:
                errors = 'strict'
        elif not isinstance(errors, str):
            raise TypeError("invalid errors: %r" % errors)

        if encoding is None:
            encoding = self._encoding
        else:
            if not isinstance(encoding, str):
                raise TypeError("invalid encoding: %r" % encoding)
            if encoding == "locale":
                encoding = self._get_locale_encoding()

        if newline is Ellipsis:
            newline = self._readnl
        self._check_newline(newline)

        if line_buffering is None:
            line_buffering = self.line_buffering
        if write_through is None:
            write_through = self.write_through

        self.flush()
        self._configure(encoding, errors, newline,
                        line_buffering, write_through)

    def seekable(self):
        if self.closed:
            raise ValueError("I/O operation on closed file.")
        return self._seekable

    def readable(self):
        return self.buffer.readable()

    def writable(self):
        return self.buffer.writable()

    def flush(self):
        self.buffer.flush()
        self._telling = self._seekable

    def close(self):
        if self.buffer is not None and not self.closed:
            try:
                self.flush()
            finally:
                self.buffer.close()

    @property
    def closed(self):
        return self.buffer.closed

    @property
    def name(self):
        return self.buffer.name

    def fileno(self):
        return self.buffer.fileno()

    def isatty(self):
        return self.buffer.isatty()

    def write(self, s):
        'Write data, where s is a str'
        if self.closed:
            raise ValueError("write to closed file")
        if not isinstance(s, str):
            raise TypeError("can't write %s to text stream" %
                            s.__class__.__name__)
        length = len(s)
        haslf = (self._writetranslate or self._line_buffering) and "\n" in s
        if haslf and self._writetranslate and self._writenl != "\n":
            s = s.replace("\n", self._writenl)
        encoder = self._encoder or self._get_encoder()
        # XXX What if we were just reading?
        b = encoder.encode(s)
        self.buffer.write(b)
        if self._line_buffering and (haslf or "\r" in s):
            self.flush()
        self._set_decoded_chars('')
        self._snapshot = None
        if self._decoder:
            self._decoder.reset()
        return length

    def _get_encoder(self):
        make_encoder = codecs.getincrementalencoder(self._encoding)
        self._encoder = make_encoder(self._errors)
        return self._encoder

    def _get_decoder(self):
        make_decoder = codecs.getincrementaldecoder(self._encoding)
        decoder = make_decoder(self._errors)
        if self._readuniversal:
            decoder = IncrementalNewlineDecoder(decoder, self._readtranslate)
        self._decoder = decoder
        return decoder

    # The following three methods implement an ADT for _decoded_chars.
    # Text returned from the decoder is buffered here until the client
    # requests it by calling our read() or readline() method.
    def _set_decoded_chars(self, chars):
        """Set the _decoded_chars buffer."""
        self._decoded_chars = chars
        self._decoded_chars_used = 0

    def _get_decoded_chars(self, n=None):
        """Advance into the _decoded_chars buffer."""
        offset = self._decoded_chars_used
        if n is None:
            chars = self._decoded_chars[offset:]
        else:
            chars = self._decoded_chars[offset:offset + n]
        self._decoded_chars_used += len(chars)
        return chars

    def _get_locale_encoding(self):
        try:
            import locale
        except ImportError:
            # Importing locale may fail if Python is being built
            return "utf-8"
        else:
            return locale.getencoding()

    def _rewind_decoded_chars(self, n):
        """Rewind the _decoded_chars buffer."""
        if self._decoded_chars_used < n:
            raise AssertionError("rewind decoded_chars out of bounds")
        self._decoded_chars_used -= n

    def _read_chunk(self):
        """
        Read and decode the next chunk of data from the BufferedReader.
        """

        # The return value is True unless EOF was reached.  The decoded
        # string is placed in self._decoded_chars (replacing its previous
        # value).  The entire input chunk is sent to the decoder, though
        # some of it may remain buffered in the decoder, yet to be
        # converted.

        if self._decoder is None:
            raise ValueError("no decoder")

        if self._telling:
            # To prepare for tell(), we need to snapshot a point in the
            # file where the decoder's input buffer is empty.

            dec_buffer, dec_flags = self._decoder.getstate()
            # Given this, we know there was a valid snapshot point
            # len(dec_buffer) bytes ago with decoder state (b'', dec_flags).

        # Read a chunk, decode it, and put the result in self._decoded_chars.
        if self._has_read1:
            input_chunk = self.buffer.read1(self._CHUNK_SIZE)
        else:
            input_chunk = self.buffer.read(self._CHUNK_SIZE)
        eof = not input_chunk
        decoded_chars = self._decoder.decode(input_chunk, eof)
        self._set_decoded_chars(decoded_chars)
        if decoded_chars:
            self._b2cratio = len(input_chunk) / len(self._decoded_chars)
        else:
            self._b2cratio = 0.0

        if self._telling:
            # At the snapshot point, len(dec_buffer) bytes before the read,
            # the next input to be decoded is dec_buffer + input_chunk.
            self._snapshot = (dec_flags, dec_buffer + input_chunk)

        return not eof

    def _pack_cookie(self, position, dec_flags=0,
                           bytes_to_feed=0, need_eof=False, chars_to_skip=0):
        # The meaning of a tell() cookie is: seek to position, set the
        # decoder flags to dec_flags, read bytes_to_feed bytes, feed them
        # into the decoder with need_eof as the EOF flag, then skip
        # chars_to_skip characters of the decoded result.  For most simple
        # decoders, tell() will often just give a byte offset in the file.
        return (position | (dec_flags<<64) | (bytes_to_feed<<128) |
               (chars_to_skip<<192) | bool(need_eof)<<256)

    def _unpack_cookie(self, bigint):
        rest, position = divmod(bigint, 1<<64)
        rest, dec_flags = divmod(rest, 1<<64)
        rest, bytes_to_feed = divmod(rest, 1<<64)
        need_eof, chars_to_skip = divmod(rest, 1<<64)
        return position, dec_flags, bytes_to_feed, bool(need_eof), chars_to_skip

    def tell(self):
        if not self._seekable:
            raise UnsupportedOperation("underlying stream is not seekable")
        if not self._telling:
            raise OSError("telling position disabled by next() call")
        self.flush()
        position = self.buffer.tell()
        decoder = self._decoder
        if decoder is None or self._snapshot is None:
            if self._decoded_chars:
                # This should never happen.
                raise AssertionError("pending decoded text")
            return position

        # Skip backward to the snapshot point (see _read_chunk).
        dec_flags, next_input = self._snapshot
        position -= len(next_input)

        # How many decoded characters have been used up since the snapshot?
        chars_to_skip = self._decoded_chars_used
        if chars_to_skip == 0:
            # We haven't moved from the snapshot point.
            return self._pack_cookie(position, dec_flags)

        # Starting from the snapshot position, we will walk the decoder
        # forward until it gives us enough decoded characters.
        saved_state = decoder.getstate()
        try:
            # Fast search for an acceptable start point, close to our
            # current pos.
            # Rationale: calling decoder.decode() has a large overhead
            # regardless of chunk size; we want the number of such calls to
            # be O(1) in most situations (common decoders, sensible input).
            # Actually, it will be exactly 1 for fixed-size codecs (all
            # 8-bit codecs, also UTF-16 and UTF-32).
            skip_bytes = int(self._b2cratio * chars_to_skip)
            skip_back = 1
            assert skip_bytes <= len(next_input)
            while skip_bytes > 0:
                decoder.setstate((b'', dec_flags))
                # Decode up to temptative start point
                n = len(decoder.decode(next_input[:skip_bytes]))
                if n <= chars_to_skip:
                    b, d = decoder.getstate()
                    if not b:
                        # Before pos and no bytes buffered in decoder => OK
                        dec_flags = d
                        chars_to_skip -= n
                        break
                    # Skip back by buffered amount and reset heuristic
                    skip_bytes -= len(b)
                    skip_back = 1
                else:
                    # We're too far ahead, skip back a bit
                    skip_bytes -= skip_back
                    skip_back = skip_back * 2
            else:
                skip_bytes = 0
                decoder.setstate((b'', dec_flags))

            # Note our initial start point.
            start_pos = position + skip_bytes
            start_flags = dec_flags
            if chars_to_skip == 0:
                # We haven't moved from the start point.
                return self._pack_cookie(start_pos, start_flags)

            # Feed the decoder one byte at a time.  As we go, note the
            # nearest "safe start point" before the current location
            # (a point where the decoder has nothing buffered, so seek()
            # can safely start from there and advance to this location).
            bytes_fed = 0
            need_eof = False
            # Chars decoded since `start_pos`
            chars_decoded = 0
            for i in range(skip_bytes, len(next_input)):
                bytes_fed += 1
                chars_decoded += len(decoder.decode(next_input[i:i+1]))
                dec_buffer, dec_flags = decoder.getstate()
                if not dec_buffer and chars_decoded <= chars_to_skip:
                    # Decoder buffer is empty, so this is a safe start point.
                    start_pos += bytes_fed
                    chars_to_skip -= chars_decoded
                    start_flags, bytes_fed, chars_decoded = dec_flags, 0, 0
                if chars_decoded >= chars_to_skip:
                    break
            else:
                # We didn't get enough decoded data; signal EOF to get more.
                chars_decoded += len(decoder.decode(b'', final=True))
                need_eof = True
                if chars_decoded < chars_to_skip:
                    raise OSError("can't reconstruct logical file position")

            # The returned cookie corresponds to the last safe start point.
            return self._pack_cookie(
                start_pos, start_flags, bytes_fed, need_eof, chars_to_skip)
        finally:
            decoder.setstate(saved_state)

    def truncate(self, pos=None):
        self.flush()
        if pos is None:
            pos = self.tell()
        return self.buffer.truncate(pos)

    def detach(self):
        if self.buffer is None:
            raise ValueError("buffer is already detached")
        self.flush()
        buffer = self._buffer
        self._buffer = None
        return buffer

    def seek(self, cookie, whence=0):
        def _reset_encoder(position):
            """Reset the encoder (merely useful for proper BOM handling)"""
            try:
                encoder = self._encoder or self._get_encoder()
            except LookupError:
                # Sometimes the encoder doesn't exist
                pass
            else:
                if position != 0:
                    encoder.setstate(0)
                else:
                    encoder.reset()

        if self.closed:
            raise ValueError("tell on closed file")
        if not self._seekable:
            raise UnsupportedOperation("underlying stream is not seekable")
        if whence == SEEK_CUR:
            if cookie != 0:
                raise UnsupportedOperation("can't do nonzero cur-relative seeks")
            # Seeking to the current position should attempt to
            # sync the underlying buffer with the current position.
            whence = 0
            cookie = self.tell()
        elif whence == SEEK_END:
            if cookie != 0:
                raise UnsupportedOperation("can't do nonzero end-relative seeks")
            self.flush()
            position = self.buffer.seek(0, whence)
            self._set_decoded_chars('')
            self._snapshot = None
            if self._decoder:
                self._decoder.reset()
            _reset_encoder(position)
            return position
        if whence != 0:
            raise ValueError("unsupported whence (%r)" % (whence,))
        if cookie < 0:
            raise ValueError("negative seek position %r" % (cookie,))
        self.flush()

        # The strategy of seek() is to go back to the safe start point
        # and replay the effect of read(chars_to_skip) from there.
        start_pos, dec_flags, bytes_to_feed, need_eof, chars_to_skip = \
            self._unpack_cookie(cookie)

        # Seek back to the safe start point.
        self.buffer.seek(start_pos)
        self._set_decoded_chars('')
        self._snapshot = None

        # Restore the decoder to its state from the safe start point.
        if cookie == 0 and self._decoder:
            self._decoder.reset()
        elif self._decoder or dec_flags or chars_to_skip:
            self._decoder = self._decoder or self._get_decoder()
            self._decoder.setstate((b'', dec_flags))
            self._snapshot = (dec_flags, b'')

        if chars_to_skip:
            # Just like _read_chunk, feed the decoder and save a snapshot.
            input_chunk = self.buffer.read(bytes_to_feed)
            self._set_decoded_chars(
                self._decoder.decode(input_chunk, need_eof))
            self._snapshot = (dec_flags, input_chunk)

            # Skip chars_to_skip of the decoded characters.
            if len(self._decoded_chars) < chars_to_skip:
                raise OSError("can't restore logical file position")
            self._decoded_chars_used = chars_to_skip

        _reset_encoder(cookie)
        return cookie

    def read(self, size=None):
        self._checkReadable()
        if size is None:
            size = -1
        else:
            try:
                size_index = size.__index__
            except AttributeError:
                raise TypeError(f"{size!r} is not an integer")
            else:
                size = size_index()
        decoder = self._decoder or self._get_decoder()
        if size < 0:
            # Read everything.
            result = (self._get_decoded_chars() +
                      decoder.decode(self.buffer.read(), final=True))
            self._set_decoded_chars('')
            self._snapshot = None
            return result
        else:
            # Keep reading chunks until we have size characters to return.
            eof = False
            result = self._get_decoded_chars(size)
            while len(result) < size and not eof:
                eof = not self._read_chunk()
                result += self._get_decoded_chars(size - len(result))
            return result

    def __next__(self):
        self._telling = False
        line = self.readline()
        if not line:
            self._snapshot = None
            self._telling = self._seekable
            raise StopIteration
        return line

    def readline(self, size=None):
        if self.closed:
            raise ValueError("read from closed file")
        if size is None:
            size = -1
        else:
            try:
                size_index = size.__index__
            except AttributeError:
                raise TypeError(f"{size!r} is not an integer")
            else:
                size = size_index()

        # Grab all the decoded text (we will rewind any extra bits later).
        line = self._get_decoded_chars()

        start = 0
        # Make the decoder if it doesn't already exist.
        if not self._decoder:
            self._get_decoder()

        pos = endpos = None
        while True:
            if self._readtranslate:
                # Newlines are already translated, only search for \n
                pos = line.find('\n', start)
                if pos >= 0:
                    endpos = pos + 1
                    break
                else:
                    start = len(line)

            elif self._readuniversal:
                # Universal newline search. Find any of \r, \r\n, \n
                # The decoder ensures that \r\n are not split in two pieces

                # In C we'd look for these in parallel of course.
                nlpos = line.find("\n", start)
                crpos = line.find("\r", start)
                if crpos == -1:
                    if nlpos == -1:
                        # Nothing found
                        start = len(line)
                    else:
                        # Found \n
                        endpos = nlpos + 1
                        break
                elif nlpos == -1:
                    # Found lone \r
                    endpos = crpos + 1
                    break
                elif nlpos < crpos:
                    # Found \n
                    endpos = nlpos + 1
                    break
                elif nlpos == crpos + 1:
                    # Found \r\n
                    endpos = crpos + 2
                    break
                else:
                    # Found \r
                    endpos = crpos + 1
                    break
            else:
                # non-universal
                pos = line.find(self._readnl)
                if pos >= 0:
                    endpos = pos + len(self._readnl)
                    break

            if size >= 0 and len(line) >= size:
                endpos = size  # reached length size
                break

            # No line ending seen yet - get more data'
            while self._read_chunk():
                if self._decoded_chars:
                    break
            if self._decoded_chars:
                line += self._get_decoded_chars()
            else:
                # end of file
                self._set_decoded_chars('')
                self._snapshot = None
                return line

        if size >= 0 and endpos > size:
            endpos = size  # don't exceed size

        # Rewind _decoded_chars to just after the line ending we found.
        self._rewind_decoded_chars(len(line) - endpos)
        return line[:endpos]

    @property
    def newlines(self):
        return self._decoder.newlines if self._decoder else None


class StringIO(TextIOWrapper):
    """Text I/O implementation using an in-memory buffer.

    The initial_value argument sets the value of object.  The newline
    argument is like the one of TextIOWrapper's constructor.
    """

    def __init__(self, initial_value="", newline="\n"):
        super(StringIO, self).__init__(BytesIO(),
                                       encoding="utf-8",
                                       errors="surrogatepass",
                                       newline=newline)
        # Issue #5645: make universal newlines semantics the same as in the
        # C version, even under Windows.
        if newline is None:
            self._writetranslate = False
        if initial_value is not None:
            if not isinstance(initial_value, str):
                raise TypeError("initial_value must be str or None, not {0}"
                                .format(type(initial_value).__name__))
            self.write(initial_value)
            self.seek(0)

    def getvalue(self):
        self.flush()
        decoder = self._decoder or self._get_decoder()
        old_state = decoder.getstate()
        decoder.reset()
        try:
            return decoder.decode(self.buffer.getvalue(), final=True)
        finally:
            decoder.setstate(old_state)

    def __repr__(self):
        # TextIOWrapper tells the encoding in its repr. In StringIO,
        # that's an implementation detail.
        return object.__repr__(self)

    @property
    def errors(self):
        return None

    @property
    def encoding(self):
        return None

    def detach(self):
        # This doesn't make sense on StringIO.
        self._unsupported("detach")
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            # Copyright (c) 2004 Python Software Foundation.
# All rights reserved.

# Written by Eric Price <eprice at tjhsst.edu>
#    and Facundo Batista <facundo at taniquetil.com.ar>
#    and Raymond Hettinger <python at rcn.com>
#    and Aahz <aahz at pobox.com>
#    and Tim Peters

# This module should be kept in sync with the latest updates of the
# IBM specification as it evolves.  Those updates will be treated
# as bug fixes (deviation from the spec is a compatibility, usability
# bug) and will be backported.  At this point the spec is stabilizing
# and the updates are becoming fewer, smaller, and less significant.

"""
This is an implementation of decimal floating point arithmetic based on
the General Decimal Arithmetic Specification:

    http://speleotrove.com/decimal/decarith.html

and IEEE standard 854-1987:

    http://en.wikipedia.org/wiki/IEEE_854-1987

Decimal floating point has finite precision with arbitrarily large bounds.

The purpose of this module is to support arithmetic using familiar
"schoolhouse" rules and to avoid some of the tricky representation
issues associated with binary floating point.  The package is especially
useful for financial applications or for contexts where users have
expectations that are at odds with binary floating point (for instance,
in binary floating point, 1.00 % 0.1 gives 0.09999999999999995 instead
of 0.0; Decimal('1.00') % Decimal('0.1') returns the expected
Decimal('0.00')).

Here are some examples of using the decimal module:

>>> from decimal import *
>>> setcontext(ExtendedContext)
>>> Decimal(0)
Decimal('0')
>>> Decimal('1')
Decimal('1')
>>> Decimal('-.0123')
Decimal('-0.0123')
>>> Decimal(123456)
Decimal('123456')
>>> Decimal('123.45e12345678')
Decimal('1.2345E+12345680')
>>> Decimal('1.33') + Decimal('1.27')
Decimal('2.60')
>>> Decimal('12.34') + Decimal('3.87') - Decimal('18.41')
Decimal('-2.20')
>>> dig = Decimal(1)
>>> print(dig / Decimal(3))
0.333333333
>>> getcontext().prec = 18
>>> print(dig / Decimal(3))
0.333333333333333333
>>> print(dig.sqrt())
1
>>> print(Decimal(3).sqrt())
1.73205080756887729
>>> print(Decimal(3) ** 123)
4.85192780976896427E+58
>>> inf = Decimal(1) / Decimal(0)
>>> print(inf)
Infinity
>>> neginf = Decimal(-1) / Decimal(0)
>>> print(neginf)
-Infinity
>>> print(neginf + inf)
NaN
>>> print(neginf * inf)
-Infinity
>>> print(dig / 0)
Infinity
>>> getcontext().traps[DivisionByZero] = 1
>>> print(dig / 0)
Traceback (most recent call last):
  ...
  ...
  ...
decimal.DivisionByZero: x / 0
>>> c = Context()
>>> c.traps[InvalidOperation] = 0
>>> print(c.flags[InvalidOperation])
0
>>> c.divide(Decimal(0), Decimal(0))
Decimal('NaN')
>>> c.traps[InvalidOperation] = 1
>>> print(c.flags[InvalidOperation])
1
>>> c.flags[InvalidOperation] = 0
>>> print(c.flags[InvalidOperation])
0
>>> print(c.divide(Decimal(0), Decimal(0)))
Traceback (most recent call last):
  ...
  ...
  ...
decimal.InvalidOperation: 0 / 0
>>> print(c.flags[InvalidOperation])
1
>>> c.flags[InvalidOperation] = 0
>>> c.traps[InvalidOperation] = 0
>>> print(c.divide(Decimal(0), Decimal(0)))
NaN
>>> print(c.flags[InvalidOperation])
1
>>>
"""

__all__ = [
    # Two major classes
    'Decimal', 'Context',

    # Named tuple representation
    'DecimalTuple',

    # Contexts
    'DefaultContext', 'BasicContext', 'ExtendedContext',

    # Exceptions
    'DecimalException', 'Clamped', 'InvalidOperation', 'DivisionByZero',
    'Inexact', 'Rounded', 'Subnormal', 'Overflow', 'Underflow',
    'FloatOperation',

    # Exceptional conditions that trigger InvalidOperation
    'DivisionImpossible', 'InvalidContext', 'ConversionSyntax', 'DivisionUndefined',

    # Constants for use in setting up contexts
    'ROUND_DOWN', 'ROUND_HALF_UP', 'ROUND_HALF_EVEN', 'ROUND_CEILING',
    'ROUND_FLOOR', 'ROUND_UP', 'ROUND_HALF_DOWN', 'ROUND_05UP',

    # Functions for manipulating contexts
    'setcontext', 'getcontext', 'localcontext',

    # Limits for the C version for compatibility
    'MAX_PREC',  'MAX_EMAX', 'MIN_EMIN', 'MIN_ETINY',

    # C version: compile time choice that enables the thread local context (deprecated, now always true)
    'HAVE_THREADS',

    # C version: compile time choice that enables the coroutine local context
    'HAVE_CONTEXTVAR'
]

__xname__ = __name__    # sys.modules lookup (--without-threads)
__name__ = 'decimal'    # For pickling
__version__ = '1.70'    # Highest version of the spec this complies with
                        # See http://speleotrove.com/decimal/
__libmpdec_version__ = "2.4.2" # compatible libmpdec version

import math as _math
import numbers as _numbers
import sys

try:
    from collections import namedtuple as _namedtuple
    DecimalTuple = _namedtuple('DecimalTuple', 'sign digits exponent')
except ImportError:
    DecimalTuple = lambda *args: args

# Rounding
ROUND_DOWN = 'ROUND_DOWN'
ROUND_HALF_UP = 'ROUND_HALF_UP'
ROUND_HALF_EVEN = 'ROUND_HALF_EVEN'
ROUND_CEILING = 'ROUND_CEILING'
ROUND_FLOOR = 'ROUND_FLOOR'
ROUND_UP = 'ROUND_UP'
ROUND_HALF_DOWN = 'ROUND_HALF_DOWN'
ROUND_05UP = 'ROUND_05UP'

# Compatibility with the C version
HAVE_THREADS = True
HAVE_CONTEXTVAR = True
if sys.maxsize == 2**63-1:
    MAX_PREC = 999999999999999999
    MAX_EMAX = 999999999999999999
    MIN_EMIN = -999999999999999999
else:
    MAX_PREC = 425000000
    MAX_EMAX = 425000000
    MIN_EMIN = -425000000

MIN_ETINY = MIN_EMIN - (MAX_PREC-1)

# Errors

class DecimalException(ArithmeticError):
    """Base exception class.

    Used exceptions derive from this.
    If an exception derives from another exception besides this (such as
    Underflow (Inexact, Rounded, Subnormal) that indicates that it is only
    called if the others are present.  This isn't actually used for
    anything, though.

    handle  -- Called when context._raise_error is called and the
               trap_enabler is not set.  First argument is self, second is the
               context.  More arguments can be given, those being after
               the explanation in _raise_error (For example,
               context._raise_error(NewError, '(-x)!', self._sign) would
               call NewError().handle(context, self._sign).)

    To define a new exception, it should be sufficient to have it derive
    from DecimalException.
    """
    def handle(self, context, *args):
        pass


class Clamped(DecimalException):
    """Exponent of a 0 changed to fit bounds.

    This occurs and signals clamped if the exponent of a result has been
    altered in order to fit the constraints of a specific concrete
    representation.  This may occur when the exponent of a zero result would
    be outside the bounds of a representation, or when a large normal
    number would have an encoded exponent that cannot be represented.  In
    this latter case, the exponent is reduced to fit and the corresponding
    number of zero digits are appended to the coefficient ("fold-down").
    """

class InvalidOperation(DecimalException):
    """An invalid operation was performed.

    Various bad things cause this:

    Something creates a signaling NaN
    -INF + INF
    0 * (+-)INF
    (+-)INF / (+-)INF
    x % 0
    (+-)INF % x
    x._rescale( non-integer )
    sqrt(-x) , x > 0
    0 ** 0
    x ** (non-integer)
    x ** (+-)INF
    An operand is invalid

    The result of the operation after these is a quiet positive NaN,
    except when the cause is a signaling NaN, in which case the result is
    also a quiet NaN, but with the original sign, and an optional
    diagnostic information.
    """
    def handle(self, context, *args):
        if args:
            ans = _dec_from_triple(args[0]._sign, args[0]._int, 'n', True)
            return ans._fix_nan(context)
        return _NaN

class ConversionSyntax(InvalidOperation):
    """Trying to convert badly formed string.

    This occurs and signals invalid-operation if a string is being
    converted to a number and it does not conform to the numeric string
    syntax.  The result is [0,qNaN].
    """
    def handle(self, context, *args):
        return _NaN

class DivisionByZero(DecimalException, ZeroDivisionError):
    """Division by 0.

    This occurs and signals division-by-zero if division of a finite number
    by zero was attempted (during a divide-integer or divide operation, or a
    power operation with negative right-hand operand), and the dividend was
    not zero.

    The result of the operation is [sign,inf], where sign is the exclusive
    or of the signs of the operands for divide, or is 1 for an odd power of
    -0, for power.
    """

    def handle(self, context, sign, *args):
        return _SignedInfinity[sign]

class DivisionImpossible(InvalidOperation):
    """Cannot perform the division adequately.

    This occurs and signals invalid-operation if the integer result of a
    divide-integer or remainder operation had too many digits (would be
    longer than precision).  The result is [0,qNaN].
    """

    def handle(self, context, *args):
        return _NaN

class DivisionUndefined(InvalidOperation, ZeroDivisionError):
    """Undefined result of division.

    This occurs and signals invalid-operation if division by zero was
    attempted (during a divide-integer, divide, or remainder operation), and
    the dividend is also zero.  The result is [0,qNaN].
    """

    def handle(self, context, *args):
        return _NaN

class Inexact(DecimalException):
    """Had to round, losing information.

    This occurs and signals inexact whenever the result of an operation is
    not exact (that is, it needed to be rounded and any discarded digits
    were non-zero), or if an overflow or underflow condition occurs.  The
    result in all cases is unchanged.

    The inexact signal may be tested (or trapped) to determine if a given
    operation (or sequence of operations) was inexact.
    """

class InvalidContext(InvalidOperation):
    """Invalid context.  Unknown rounding, for example.

    This occurs and signals invalid-operation if an invalid context was
    detected during an operation.  This can occur if contexts are not checked
    on creation and either the precision exceeds the capability of the
    underlying concrete representation or an unknown or unsupported rounding
    was specified.  These aspects of the context need only be checked when
    the values are required to be used.  The result is [0,qNaN].
    """

    def handle(self, context, *args):
        return _NaN

class Rounded(DecimalException):
    """Number got rounded (not  necessarily changed during rounding).

    This occurs and signals rounded whenever the result of an operation is
    rounded (that is, some zero or non-zero digits were discarded from the
    coefficient), or if an overflow or underflow condition occurs.  The
    result in all cases is unchanged.

    The rounded signal may be tested (or trapped) to determine if a given
    operation (or sequence of operations) caused a loss of precision.
    """

class Subnormal(DecimalException):
    """Exponent < Emin before rounding.

    This occurs and signals subnormal whenever the result of a conversion or
    operation is subnormal (that is, its adjusted exponent is less than
    Emin, before any rounding).  The result in all cases is unchanged.

    The subnormal signal may be tested (or trapped) to determine if a given
    or operation (or sequence of operations) yielded a subnormal result.
    """

class Overflow(Inexact, Rounded):
    """Numerical overflow.

    This occurs and signals overflow if the adjusted exponent of a result
    (from a conversion or from an operation that is not an attempt to divide
    by zero), after rounding, would be greater than the largest value that
    can be handled by the implementation (the value Emax).

    The result depends on the rounding mode:

    For round-half-up and round-half-even (and for round-half-down and
    round-up, if implemented), the result of the operation is [sign,inf],
    where sign is the sign of the intermediate result.  For round-down, the
    result is the largest finite number that can be represented in the
    current precision, with the sign of the intermediate result.  For
    round-ceiling, the result is the same as for round-down if the sign of
    the intermediate result is 1, or is [0,inf] otherwise.  For round-floor,
    the result is the same as for round-down if the sign of the intermediate
    result is 0, or is [1,inf] otherwise.  In all cases, Inexact and Rounded
    will also be raised.
    """

    def handle(self, context, sign, *args):
        if context.rounding in (ROUND_HALF_UP, ROUND_HALF_EVEN,
                                ROUND_HALF_DOWN, ROUND_UP):
            return _SignedInfinity[sign]
        if sign == 0:
            if context.rounding == ROUND_CEILING:
                return _SignedInfinity[sign]
            return _dec_from_triple(sign, '9'*context.prec,
                            context.Emax-context.prec+1)
        if sign == 1:
            if context.rounding == ROUND_FLOOR:
                return _SignedInfinity[sign]
            return _dec_from_triple(sign, '9'*context.prec,
                             context.Emax-context.prec+1)


class Underflow(Inexact, Rounded, Subnormal):
    """Numerical underflow with result rounded to 0.

    This occurs and signals underflow if a result is inexact and the
    adjusted exponent of the result would be smaller (more negative) than
    the smallest value that can be handled by the implementation (the value
    Emin).  That is, the result is both inexact and subnormal.

    The result after an underflow will be a subnormal number rounded, if
    necessary, so that its exponent is not less than Etiny.  This may result
    in 0 with the sign of the intermediate result and an exponent of Etiny.

    In all cases, Inexact, Rounded, and Subnormal will also be raised.
    """

class FloatOperation(DecimalException, TypeError):
    """Enable stricter semantics for mixing floats and Decimals.

    If the signal is not trapped (default), mixing floats and Decimals is
    permitted in the Decimal() constructor, context.create_decimal() and
    all comparison operators. Both conversion and comparisons are exact.
    Any occurrence of a mixed operation is silently recorded by setting
    FloatOperation in the context flags.  Explicit conversions with
    Decimal.from_float() or context.create_decimal_from_float() do not
    set the flag.

    Otherwise (the signal is trapped), only equality comparisons and explicit
    conversions are silent. All other mixed operations raise FloatOperation.
    """

# List of public traps and flags
_signals = [Clamped, DivisionByZero, Inexact, Overflow, Rounded,
            Underflow, InvalidOperation, Subnormal, FloatOperation]

# Map conditions (per the spec) to signals
_condition_map = {ConversionSyntax:InvalidOperation,
                  DivisionImpossible:InvalidOperation,
                  DivisionUndefined:InvalidOperation,
                  InvalidContext:InvalidOperation}

# Valid rounding modes
_rounding_modes = (ROUND_DOWN, ROUND_HALF_UP, ROUND_HALF_EVEN, ROUND_CEILING,
                   ROUND_FLOOR, ROUND_UP, ROUND_HALF_DOWN, ROUND_05UP)

##### Context Functions ##################################################

# The getcontext() and setcontext() function manage access to a thread-local
# current context.

import contextvars

_current_context_var = contextvars.ContextVar('decimal_context')

_context_attributes = frozenset(
    ['prec', 'Emin', 'Emax', 'capitals', 'clamp', 'rounding', 'flags', 'traps']
)

def getcontext():
    """Returns this thread's context.

    If this thread does not yet have a context, returns
    a new context and sets this thread's context.
    New contexts are copies of DefaultContext.
    """
    try:
        return _current_context_var.get()
    except LookupError:
        context = Context()
        _current_context_var.set(context)
        return context

def setcontext(context):
    """Set this thread's context to context."""
    if context in (DefaultContext, BasicContext, ExtendedContext):
        context = context.copy()
        context.clear_flags()
    _current_context_var.set(context)

del contextvars        # Don't contaminate the namespace

def localcontext(ctx=None, **kwargs):
    """Return a context manager for a copy of the supplied context

    Uses a copy of the current context if no context is specified
    The returned context manager creates a local decimal context
    in a with statement:
        def sin(x):
             with localcontext() as ctx:
                 ctx.prec += 2
                 # Rest of sin calculation algorithm
                 # uses a precision 2 greater than normal
             return +s  # Convert result to normal precision

         def sin(x):
             with localcontext(ExtendedContext):
                 # Rest of sin calculation algorithm
                 # uses the Extended Context from the
                 # General Decimal Arithmetic Specification
             return +s  # Convert result to normal context

    >>> setcontext(DefaultContext)
    >>> print(getcontext().prec)
    28
    >>> with localcontext():
    ...     ctx = getcontext()
    ...     ctx.prec += 2
    ...     print(ctx.prec)
    ...
    30
    >>> with localcontext(ExtendedContext):
    ...     print(getcontext().prec)
    ...
    9
    >>> print(getcontext().prec)
    28
    """
    if ctx is None:
        ctx = getcontext()
    ctx_manager = _ContextManager(ctx)
    for key, value in kwargs.items():
        if key not in _context_attributes:
            raise TypeError(f"'{key}' is an invalid keyword argument for this function")
        setattr(ctx_manager.new_context, key, value)
    return ctx_manager


##### Decimal class #######################################################

# Do not subclass Decimal from numbers.Real and do not register it as such
# (because Decimals are not interoperable with floats).  See the notes in
# numbers.py for more detail.

class Decimal(object):
    """Floating point class for decimal arithmetic."""

    __slots__ = ('_exp','_int','_sign', '_is_special')
    # Generally, the value of the Decimal instance is given by
    #  (-1)**_sign * _int * 10**_exp
    # Special values are signified by _is_special == True

    # We're immutable, so use __new__ not __init__
    def __new__(cls, value="0", context=None):
        """Create a decimal point instance.

        >>> Decimal('3.14')              # string input
        Decimal('3.14')
        >>> Decimal((0, (3, 1, 4), -2))  # tuple (sign, digit_tuple, exponent)
        Decimal('3.14')
        >>> Decimal(314)                 # int
        Decimal('314')
        >>> Decimal(Decimal(314))        # another decimal instance
        Decimal('314')
        >>> Decimal('  3.14  \\n')        # leading and trailing whitespace okay
        Decimal('3.14')
        """

        # Note that the coefficient, self._int, is actually stored as
        # a string rather than as a tuple of digits.  This speeds up
        # the "digits to integer" and "integer to digits" conversions
        # that are used in almost every arithmetic operation on
        # Decimals.  This is an internal detail: the as_tuple function
        # and the Decimal constructor still deal with tuples of
        # digits.

        self = object.__new__(cls)

        # From a string
        # REs insist on real strings, so we can too.
        if isinstance(value, str):
            m = _parser(value.strip().replace("_", ""))
            if m is None:
                if context is None:
                    context = getcontext()
                return context._raise_error(ConversionSyntax,
                                "Invalid literal for Decimal: %r" % value)

            if m.group('sign') == "-":
                self._sign = 1
            else:
                self._sign = 0
            intpart = m.group('int')
            if intpart is not None:
                # finite number
                fracpart = m.group('frac') or ''
                exp = int(m.group('exp') or '0')
                self._int = str(int(intpart+fracpart))
                self._exp = exp - len(fracpart)
                self._is_special = False
            else:
                diag = m.group('diag')
                if diag is not None:
                    # NaN
                    self._int = str(int(diag or '0')).lstrip('0')
                    if m.group('signal'):
                        self._exp = 'N'
                    else:
                        self._exp = 'n'
                else:
                    # infinity
                    self._int = '0'
                    self._exp = 'F'
                self._is_special = True
            return self

        # From an integer
        if isinstance(value, int):
            if value >= 0:
                self._sign = 0
            else:
                self._sign = 1
            self._exp = 0
            self._int = str(abs(value))
            self._is_special = False
            return self

        # From another decimal
        if isinstance(value, Decimal):
            self._exp  = value._exp
            self._sign = value._sign
            self._int  = value._int
            self._is_special  = value._is_special
            return self

        # From an internal working value
        if isinstance(value, _WorkRep):
            self._sign = value.sign
            self._int = str(value.int)
            self._exp = int(value.exp)
            self._is_special = False
            return self

        # tuple/list conversion (possibly from as_tuple())
        if isinstance(value, (list,tuple)):
            if len(value) != 3:
                raise ValueError('Invalid tuple size in creation of Decimal '
                                 'from list or tuple.  The list or tuple '
                                 'should have exactly three elements.')
            # process sign.  The isinstance test rejects floats
            if not (isinstance(value[0], int) and value[0] in (0,1)):
                raise ValueError("Invalid sign.  The first value in the tuple "
                                 "should be an integer; either 0 for a "
                                 "positive number or 1 for a negative number.")
            self._sign = value[0]
            if value[2] == 'F':
                # infinity: value[1] is ignored
                self._int = '0'
                self._exp = value[2]
                self._is_special = True
            else:
                # process and validate the digits in value[1]
                digits = []
                for digit in value[1]:
                    if isinstance(digit, int) and 0 <= digit <= 9:
                        # skip leading zeros
                        if digits or digit != 0:
                            digits.append(digit)
                    else:
                        raise ValueError("The second value in the tuple must "
                                         "be composed of integers in the range "
                                         "0 through 9.")
                if value[2] in ('n', 'N'):
                    # NaN: digits form the diagnostic
                    self._int = ''.join(map(str, digits))
                    self._exp = value[2]
                    self._is_special = True
                elif isinstance(value[2], int):
                    # finite number: digits give the coefficient
                    self._int = ''.join(map(str, digits or [0]))
                    self._exp = value[2]
                    self._is_special = False
                else:
                    raise ValueError("The third value in the tuple must "
                                     "be an integer, or one of the "
                                     "strings 'F', 'n', 'N'.")
            return self

        if isinstance(value, float):
            if context is None:
                context = getcontext()
            context._raise_error(FloatOperation,
                "strict semantics for mixing floats and Decimals are "
                "enabled")
            value = Decimal.from_float(value)
            self._exp  = value._exp
            self._sign = value._sign
            self._int  = value._int
            self._is_special  = value._is_special
            return self

        raise TypeError("Cannot convert %r to Decimal" % value)

    @classmethod
    def from_float(cls, f):
        """Converts a float to a decimal number, exactly.

        Note that Decimal.from_float(0.1) is not the same as Decimal('0.1').
        Since 0.1 is not exactly representable in binary floating point, the
        value is stored as the nearest representable value which is
        0x1.999999999999ap-4.  The exact equivalent of the value in decimal
        is 0.1000000000000000055511151231257827021181583404541015625.

        >>> Decimal.from_float(0.1)
        Decimal('0.1000000000000000055511151231257827021181583404541015625')
        >>> Decimal.from_float(float('nan'))
        Decimal('NaN')
        >>> Decimal.from_float(float('inf'))
        Decimal('Infinity')
        >>> Decimal.from_float(-float('inf'))
        Decimal('-Infinity')
        >>> Decimal.from_float(-0.0)
        Decimal('-0')

        """
        if isinstance(f, int):                # handle integer inputs
            sign = 0 if f >= 0 else 1
            k = 0
            coeff = str(abs(f))
        elif isinstance(f, float):
            if _math.isinf(f) or _math.isnan(f):
                return cls(repr(f))
            if _math.copysign(1.0, f) == 1.0:
                sign = 0
            else:
                sign = 1
            n, d = abs(f).as_integer_ratio()
            k = d.bit_length() - 1
            coeff = str(n*5**k)
        else:
            raise TypeError("argument must be int or float.")

        result = _dec_from_triple(sign, coeff, -k)
        if cls is Decimal:
            return result
        else:
            return cls(result)

    def _isnan(self):
        """Returns whether the number is not actually one.

        0 if a number
        1 if NaN
        2 if sNaN
        """
        if self._is_special:
            exp = self._exp
            if exp == 'n':
                return 1
            elif exp == 'N':
                return 2
        return 0

    def _isinfinity(self):
        """Returns whether the number is infinite

        0 if finite or not a number
        1 if +INF
        -1 if -INF
        """
        if self._exp == 'F':
            if self._sign:
                return -1
            return 1
        return 0

    def _check_nans(self, other=None, context=None):
        """Returns whether the number is not actually one.

        if self, other are sNaN, signal
        if self, other are NaN return nan
        return 0

        Done before operations.
        """

        self_is_nan = self._isnan()
        if other is None:
            other_is_nan = False
        else:
            other_is_nan = other._isnan()

        if self_is_nan or other_is_nan:
            if context is None:
                context = getcontext()

            if self_is_nan == 2:
                return context._raise_error(InvalidOperation, 'sNaN',
                                        self)
            if other_is_nan == 2:
                return context._raise_error(InvalidOperation, 'sNaN',
                                        other)
            if self_is_nan:
                return self._fix_nan(context)

            return other._fix_nan(context)
        return 0

    def _compare_check_nans(self, other, context):
        """Version of _check_nans used for the signaling comparisons
        compare_signal, __le__, __lt__, __ge__, __gt__.

        Signal InvalidOperation if either self or other is a (quiet
        or signaling) NaN.  Signaling NaNs take precedence over quiet
        NaNs.

        Return 0 if neither operand is a NaN.

        """
        if context is None:
            context = getcontext()

        if self._is_special or other._is_special:
            if self.is_snan():
                return context._raise_error(InvalidOperation,
                                            'comparison involving sNaN',
                                            self)
            elif other.is_snan():
                return context._raise_error(InvalidOperation,
                                            'comparison involving sNaN',
                                            other)
            elif self.is_qnan():
                return context._raise_error(InvalidOperation,
                                            'comparison involving NaN',
                                            self)
            elif other.is_qnan():
                return context._raise_error(InvalidOperation,
                                            'comparison involving NaN',
                                            other)
        return 0

    def __bool__(self):
        """Return True if self is nonzero; otherwise return False.

        NaNs and infinities are considered nonzero.
        """
        return self._is_special or self._int != '0'

    def _cmp(self, other):
        """Compare the two non-NaN decimal instances self and other.

        Returns -1 if self < other, 0 if self == other and 1
        if self > other.  This routine is for internal use only."""

        if self._is_special or other._is_special:
            self_inf = self._isinfinity()
            other_inf = other._isinfinity()
            if self_inf == other_inf:
                return 0
            elif self_inf < other_inf:
                return -1
            else:
                return 1

        # check for zeros;  Decimal('0') == Decimal('-0')
        if not self:
            if not other:
                return 0
            else:
                return -((-1)**other._sign)
        if not other:
            return (-1)**self._sign

        # If different signs, neg one is less
        if other._sign < self._sign:
            return -1
        if self._sign < other._sign:
            return 1

        self_adjusted = self.adjusted()
        other_adjusted = other.adjusted()
        if self_adjusted == other_adjusted:
            self_padded = self._int + '0'*(self._exp - other._exp)
            other_padded = other._int + '0'*(other._exp - self._exp)
            if self_padded == other_padded:
                return 0
            elif self_padded < other_padded:
                return -(-1)**self._sign
            else:
                return (-1)**self._sign
        elif self_adjusted > other_adjusted:
            return (-1)**self._sign
        else: # self_adjusted < other_adjusted
            return -((-1)**self._sign)

    # Note: The Decimal standard doesn't cover rich comparisons for
    # Decimals.  In particular, the specification is silent on the
    # subject of what should happen for a comparison involving a NaN.
    # We take the following approach:
    #
    #   == comparisons involving a quiet NaN always return False
    #   != comparisons involving a quiet NaN always return True
    #   == or != comparisons involving a signaling NaN signal
    #      InvalidOperation, and return False or True as above if the
    #      InvalidOperation is not trapped.
    #   <, >, <= and >= comparisons involving a (quiet or signaling)
    #      NaN signal InvalidOperation, and return False if the
    #      InvalidOperation is not trapped.
    #
    # This behavior is designed to conform as closely as possible to
    # that specified by IEEE 754.

    def __eq__(self, other, context=None):
        self, other = _convert_for_comparison(self, other, equality_op=True)
        if other is NotImplemented:
            return other
        if self._check_nans(other, context):
            return False
        return self._cmp(other) == 0

    def __lt__(self, other, context=None):
        self, other = _convert_for_comparison(self, other)
        if other is NotImplemented:
            return other
        ans = self._compare_check_nans(other, context)
        if ans:
            return False
        return self._cmp(other) < 0

    def __le__(self, other, context=None):
        self, other = _convert_for_comparison(self, other)
        if other is NotImplemented:
            return other
        ans = self._compare_check_nans(other, context)
        if ans:
            return False
        return self._cmp(other) <= 0

    def __gt__(self, other, context=None):
        self, other = _convert_for_comparison(self, other)
        if other is NotImplemented:
            return other
        ans = self._compare_check_nans(other, context)
        if ans:
            return False
        return self._cmp(other) > 0

    def __ge__(self, other, context=None):
        self, other = _convert_for_comparison(self, other)
        if other is NotImplemented:
            return other
        ans = self._compare_check_nans(other, context)
        if ans:
            return False
        return self._cmp(other) >= 0

    def compare(self, other, context=None):
        """Compare self to other.  Return a decimal value:

        a or b is a NaN ==> Decimal('NaN')
        a < b           ==> Decimal('-1')
        a == b          ==> Decimal('0')
        a > b           ==> Decimal('1')
        """
        other = _convert_other(other, raiseit=True)

        # Compare(NaN, NaN) = NaN
        if (self._is_special or other and other._is_special):
            ans = self._check_nans(other, context)
            if ans:
                return ans

        return Decimal(self._cmp(other))

    def __hash__(self):
        """x.__hash__() <==> hash(x)"""

        # In order to make sure that the hash of a Decimal instance
        # agrees with the hash of a numerically equal integer, float
        # or Fraction, we follow the rules for numeric hashes outlined
        # in the documentation.  (See library docs, 'Built-in Types').
        if self._is_special:
            if self.is_snan():
                raise TypeError('Cannot hash a signaling NaN value.')
            elif self.is_nan():
                return object.__hash__(self)
            else:
                if self._sign:
                    return -_PyHASH_INF
                else:
                    return _PyHASH_INF

        if self._exp >= 0:
            exp_hash = pow(10, self._exp, _PyHASH_MODULUS)
        else:
            exp_hash = pow(_PyHASH_10INV, -self._exp, _PyHASH_MODULUS)
        hash_ = int(self._int) * exp_hash % _PyHASH_MODULUS
        ans = hash_ if self >= 0 else -hash_
        return -2 if ans == -1 else ans

    def as_tuple(self):
        """Represents the number as a triple tuple.

        To show the internals exactly as they are.
        """
        return DecimalTuple(self._sign, tuple(map(int, self._int)), self._exp)

    def as_integer_ratio(self):
        """Express a finite Decimal instance in the form n / d.

        Returns a pair (n, d) of integers.  When called on an infinity
        or NaN, raises OverflowError or ValueError respectively.

        >>> Decimal('3.14').as_integer_ratio()
        (157, 50)
        >>> Decimal('-123e5').as_integer_ratio()
        (-12300000, 1)
        >>> Decimal('0.00').as_integer_ratio()
        (0, 1)

        """
        if self._is_special:
            if self.is_nan():
                raise ValueError("cannot convert NaN to integer ratio")
            else:
                raise OverflowError("cannot convert Infinity to integer ratio")

        if not self:
            return 0, 1

        # Find n, d in lowest terms such that abs(self) == n / d;
        # we'll deal with the sign later.
        n = int(self._int)
        if self._exp >= 0:
            # self is an integer.
            n, d = n * 10**self._exp, 1
        else:
            # Find d2, d5 such that abs(self) = n / (2**d2 * 5**d5).
            d5 = -self._exp
            while d5 > 0 and n % 5 == 0:
                n //= 5
                d5 -= 1

            # (n & -n).bit_length() - 1 counts trailing zeros in binary
            # representation of n (provided n is nonzero).
            d2 = -self._exp
            shift2 = min((n & -n).bit_length() - 1, d2)
            if shift2:
                n >>= shift2
                d2 -= shift2

            d = 5**d5 << d2

        if self._sign:
            n = -n
        return n, d

    def __repr__(self):
        """Represents the number as an instance of Decimal."""
        # Invariant:  eval(repr(d)) == d
        return "Decimal('%s')" % str(self)

    def __str__(self, eng=False, context=None):
        """Return string representation of the number in scientific notation.

        Captures all of the information in the underlying representation.
        """

        sign = ['', '-'][self._sign]
        if self._is_special:
            if self._exp == 'F':
                return sign + 'Infinity'
            elif self._exp == 'n':
                return sign + 'NaN' + self._int
            else: # self._exp == 'N'
                return sign + 'sNaN' + self._int

        # number of digits of self._int to left of decimal point
        leftdigits = self._exp + len(self._int)

        # dotplace is number of digits of self._int to the left of the
        # decimal point in the mantissa of the output string (that is,
        # after adjusting the exponent)
        if self._exp <= 0 and leftdigits > -6:
            # no exponent required
            dotplace = leftdigits
        elif not eng:
            # usual scientific notation: 1 digit on left of the point
            dotplace = 1
        elif self._int == '0':
            # engineering notation, zero
            dotplace = (leftdigits + 1) % 3 - 1
        else:
            # engineering notation, nonzero
            dotplace = (leftdigits - 1) % 3 + 1

        if dotplace <= 0:
            intpart = '0'
            fracpart = '.' + '0'*(-dotplace) + self._int
        elif dotplace >= len(self._int):
            intpart = self._int+'0'*(dotplace-len(self._int))
            fracpart = ''
        else:
            intpart = self._int[:dotplace]
            fracpart = '.' + self._int[dotplace:]
        if leftdigits == dotplace:
            exp = ''
        else:
            if context is None:
                context = getcontext()
            exp = ['e', 'E'][context.capitals] + "%+d" % (leftdigits-dotplace)

        return sign + intpart + fracpart + exp

    def to_eng_string(self, context=None):
        """Convert to a string, using engineering notation if an exponent is needed.

        Engineering notation has an exponent which is a multiple of 3.  This
        can leave up to 3 digits to the left of the decimal place and may
        require the addition of either one or two trailing zeros.
        """
        return self.__str__(eng=True, context=context)

    def __neg__(self, context=None):
        """Returns a copy with the sign switched.

        Rounds, if it has reason.
        """
        if self._is_special:
            ans = self._check_nans(context=context)
            if ans:
                return ans

        if context is None:
            context = getcontext()

        if not self and context.rounding != ROUND_FLOOR:
            # -Decimal('0') is Decimal('0'), not Decimal('-0'), except
            # in ROUND_FLOOR rounding mode.
            ans = self.copy_abs()
        else:
            ans = self.copy_negate()

        return ans._fix(context)

    def __pos__(self, context=None):
        """Returns a copy, unless it is a sNaN.

        Rounds the number (if more than precision digits)
        """
        if self._is_special:
            ans = self._check_nans(context=context)
            if ans:
                return ans

        if context is None:
            context = getcontext()

        if not self and context.rounding != ROUND_FLOOR:
            # + (-0) = 0, except in ROUND_FLOOR rounding mode.
            ans = self.copy_abs()
        else:
            ans = Decimal(self)

        return ans._fix(context)

    def __abs__(self, round=True, context=None):
        """Returns the absolute value of self.

        If the keyword argument 'round' is false, do not round.  The
        expression self.__abs__(round=False) is equivalent to
        self.copy_abs().
        """
        if not round:
            return self.copy_abs()

        if self._is_special:
            ans = self._check_nans(context=context)
            if ans:
                return ans

        if self._sign:
            ans = self.__neg__(context=context)
        else:
            ans = self.__pos__(context=context)

        return ans

    def __add__(self, other, context=None):
        """Returns self + other.

        -INF + INF (or the reverse) cause InvalidOperation errors.
        """
        other = _convert_other(other)
        if other is NotImplemented:
            return other

        if context is None:
            context = getcontext()

        if self._is_special or other._is_special:
            ans = self._check_nans(other, context)
            if ans:
                return ans

            if self._isinfinity():
                # If both INF, same sign => same as both, opposite => error.
                if self._sign != other._sign and other._isinfinity():
                    return context._raise_error(InvalidOperation, '-INF + INF')
                return Decimal(self)
            if other._isinfinity():
                return Decimal(other)  # Can't both be infinity here

        exp = min(self._exp, other._exp)
        negativezero = 0
        if context.rounding == ROUND_FLOOR and self._sign != other._sign:
            # If the answer is 0, the sign should be negative, in this case.
            negativezero = 1

        if not self and not other:
            sign = min(self._sign, other._sign)
            if negativezero:
                sign = 1
            ans = _dec_from_triple(sign, '0', exp)
            ans = ans._fix(context)
            return ans
        if not self:
            exp = max(exp, other._exp - context.prec-1)
            ans = other._rescale(exp, context.rounding)
            ans = ans._fix(context)
            return ans
        if not other:
            exp = max(exp, self._exp - context.prec-1)
            ans = self._rescale(exp, context.rounding)
            ans = ans._fix(context)
            return ans

        op1 = _WorkRep(self)
        op2 = _WorkRep(other)
        op1, op2 = _normalize(op1, op2, context.prec)

        result = _WorkRep()
        if op1.sign != op2.sign:
            # Equal and opposite
            if op1.int == op2.int:
                ans = _dec_from_triple(negativezero, '0', exp)
                ans = ans._fix(context)
                return ans
            if op1.int < op2.int:
                op1, op2 = op2, op1
                # OK, now abs(op1) > abs(op2)
            if op1.sign == 1:
                result.sign = 1
                op1.sign, op2.sign = op2.sign, op1.sign
            else:
                result.sign = 0
                # So we know the sign, and op1 > 0.
        elif op1.sign == 1:
            result.sign = 1
            op1.sign, op2.sign = (0, 0)
        else:
            result.sign = 0
        # Now, op1 > abs(op2) > 0

        if op2.sign == 0:
            result.int = op1.int + op2.int
        else:
            result.int = op1.int - op2.int

        result.exp = op1.exp
        ans = Decimal(result)
        ans = ans._fix(context)
        return ans

    __radd__ = __add__

    def __sub__(self, other, context=None):
        """Return self - other"""
        other = _convert_other(other)
        if other is NotImplemented:
            return other

        if self._is_special or other._is_special:
            ans = self._check_nans(other, context=context)
            if ans:
                return ans

        # self - other is computed as self + other.copy_negate()
        return self.__add__(other.copy_negate(), context=context)

    def __rsub__(self, other, context=None):
        """Return other - self"""
        other = _convert_other(other)
        if other is NotImplemented:
            return other

        return other.__sub__(self, context=context)

    def __mul__(self, other, context=None):
        """Return self * other.

        (+-) INF * 0 (or its reverse) raise InvalidOperation.
        """
        other = _convert_other(other)
        if other is NotImplemented:
            return other

        if context is None:
            context = getcontext()

        resultsign = self._sign ^ other._sign

        if self._is_special or other._is_special:
            ans = self._check_nans(other, context)
            if ans:
                return ans

            if self._isinfinity():
                if not other:
                    return context._raise_error(InvalidOperation, '(+-)INF * 0')
                return _SignedInfinity[resultsign]

            if other._isinfinity():
                if not self:
                    return context._raise_error(InvalidOperation, '0 * (+-)INF')
                return _SignedInfinity[resultsign]

        resultexp = self._exp + other._exp

        # Special case for multiplying by zero
        if not self or not other:
            ans = _dec_from_triple(resultsign, '0', resultexp)
            # Fixing in case the exponent is out of bounds
            ans = ans._fix(context)
            return ans

        # Special case for multiplying by power of 10
        if self._int == '1':
            ans = _dec_from_triple(resultsign, other._int, resultexp)
            ans = ans._fix(context)
            return ans
        if other._int == '1':
            ans = _dec_from_triple(resultsign, self._int, resultexp)
            ans = ans._fix(context)
            return ans

        op1 = _WorkRep(self)
        op2 = _WorkRep(other)

        ans = _dec_from_triple(resultsign, str(op1.int * op2.int), resultexp)
        ans = ans._fix(context)

        return ans
    __rmul__ = __mul__

    def __truediv__(self, other, context=None):
        """Return self / other."""
        other = _convert_other(other)
        if other is NotImplemented:
            return NotImplemented

        if context is None:
            context = getcontext()

        sign = self._sign ^ other._sign

        if self._is_special or other._is_special:
            ans = self._check_nans(other, context)
            if ans:
                return ans

            if self._isinfinity() and other._isinfinity():
                return context._raise_error(InvalidOperation, '(+-)INF/(+-)INF')

            if self._isinfinity():
                return _SignedInfinity[sign]

            if other._isinfinity():
                context._raise_error(Clamped, 'Division by infinity')
                return _dec_from_triple(sign, '0', context.Etiny())

        # Special cases for zeroes
        if not other:
            if not self:
                return context._raise_error(DivisionUndefined, '0 / 0')
            return context._raise_error(DivisionByZero, 'x / 0', sign)

        if not self:
            exp = self._exp - other._exp
            coeff = 0
        else:
            # OK, so neither = 0, INF or NaN
            shift = len(other._int) - len(self._int) + context.prec + 1
            exp = self._exp - other._exp - shift
            op1 = _WorkRep(self)
            op2 = _WorkRep(other)
            if shift >= 0:
                coeff, remainder = divmod(op1.int * 10**shift, op2.int)
            else:
                coeff, remainder = divmod(op1.int, op2.int * 10**-shift)
            if remainder:
                # result is not exact; adjust to ensure correct rounding
                if coeff % 5 == 0:
                    coeff += 1
            else:
                # result is exact; get as close to ideal exponent as possible
                ideal_exp = self._exp - other._exp
                while exp < ideal_exp and coeff % 10 == 0:
                    coeff //= 10
                    exp += 1

        ans = _dec_from_triple(sign, str(coeff), exp)
        return ans._fix(context)

    def _divide(self, other, context):
        """Return (self // other, self % other), to context.prec precision.

        Assumes that neither self nor other is a NaN, that self is not
        infinite and that other is nonzero.
        """
        sign = self._sign ^ other._sign
        if other._isinfinity():
            ideal_exp = self._exp
        else:
            ideal_exp = min(self._exp, other._exp)

        expdiff = self.adjusted() - other.adjusted()
        if not self or other._isinfinity() or expdiff <= -2:
            return (_dec_from_triple(sign, '0', 0),
                    self._rescale(ideal_exp, context.rounding))
        if expdiff <= context.prec:
            op1 = _WorkRep(self)
            op2 = _WorkRep(other)
            if op1.exp >= op2.exp:
                op1.int *= 10**(op1.exp - op2.exp)
            else:
                op2.int *= 10**(op2.exp - op1.exp)
            q, r = divmod(op1.int, op2.int)
            if q < 10**context.prec:
                return (_dec_from_triple(sign, str(q), 0),
                        _dec_from_triple(self._sign, str(r), ideal_exp))

        # Here the quotient is too large to be representable
        ans = context._raise_error(DivisionImpossible,
                                   'quotient too large in //, % or divmod')
        return ans, ans

    def __rtruediv__(self, other, context=None):
        """Swaps self/other and returns __truediv__."""
        other = _convert_other(other)
        if other is NotImplemented:
            return other
        return other.__truediv__(self, context=context)

    def __divmod__(self, other, context=None):
        """
        Return (self // other, self % other)
        """
        other = _convert_other(other)
        if other is NotImplemented:
            return other

        if context is None:
            context = getcontext()

        ans = self._check_nans(other, context)
        if ans:
            return (ans, ans)

        sign = self._sign ^ other._sign
        if self._isinfinity():
            if other._isinfinity():
                ans = context._raise_error(InvalidOperation, 'divmod(INF, INF)')
                return ans, ans
            else:
                return (_SignedInfinity[sign],
                        context._raise_error(InvalidOperation, 'INF % x'))

        if not other:
            if not self:
                ans = context._raise_error(DivisionUndefined, 'divmod(0, 0)')
                return ans, ans
            else:
                return (context._raise_error(DivisionByZero, 'x // 0', sign),
                        context._raise_error(InvalidOperation, 'x % 0'))

        quotient, remainder = self._divide(other, context)
        remainder = remainder._fix(context)
        return quotient, remainder

    def __rdivmod__(self, other, context=None):
        """Swaps self/other and returns __divmod__."""
        other = _convert_other(other)
        if other is NotImplemented:
            return other
        return other.__divmod__(self, context=context)

    def __mod__(self, other, context=None):
        """
        self % other
        """
        other = _convert_other(other)
        if other is NotImplemented:
            return other

        if context is None:
            context = getcontext()

        ans = self._check_nans(other, context)
        if ans:
            return ans

        if self._isinfinity():
            return context._raise_error(InvalidOperation, 'INF % x')
        elif not other:
            if self:
                return context._raise_error(InvalidOperation, 'x % 0')
            else:
                return context._raise_error(DivisionUndefined, '0 % 0')

        remainder = self._divide(other, context)[1]
        remainder = remainder._fix(context)
        return remainder

    def __rmod__(self, other, context=None):
        """Swaps self/other and returns __mod__."""
        other = _convert_other(other)
        if other is NotImplemented:
            return other
        return other.__mod__(self, context=context)

    def remainder_near(self, other, context=None):
        """
        Remainder nearest to 0-  abs(remainder-near) <= other/2
        """
        if context is None:
            context = getcontext()

        other = _convert_other(other, raiseit=True)

        ans = self._check_nans(other, context)
        if ans:
            return ans

        # self == +/-infinity -> InvalidOperation
        if self._isinfinity():
            return context._raise_error(InvalidOperation,
                                        'remainder_near(infinity, x)')

        # other == 0 -> either InvalidOperation or DivisionUndefined
        if not other:
            if self:
                return context._raise_error(InvalidOperation,
                                            'remainder_near(x, 0)')
            else:
                return context._raise_error(DivisionUndefined,
                                            'remainder_near(0, 0)')

        # other = +/-infinity -> remainder = self
        if other._isinfinity():
            ans = Decimal(self)
            return ans._fix(context)

        # self = 0 -> remainder = self, with ideal exponent
        ideal_exponent = min(self._exp, other._exp)
        if not self:
            ans = _dec_from_triple(self._sign, '0', ideal_exponent)
            return ans._fix(context)

        # catch most cases of large or small quotient
        expdiff = self.adjusted() - other.adjusted()
        if expdiff >= context.prec + 1:
            # expdiff >= prec+1 => abs(self/other) > 10**prec
            return context._raise_error(DivisionImpossible)
        if expdiff <= -2:
            # expdiff <= -2 => abs(self/other) < 0.1
            ans = self._rescale(ideal_exponent, context.rounding)
            return ans._fix(context)

        # adjust both arguments to have the same exponent, then divide
        op1 = _WorkRep(self)
        op2 = _WorkRep(other)
        if op1.exp >= op2.exp:
            op1.int *= 10**(op1.exp - op2.exp)
        else:
            op2.int *= 10**(op2.exp - op1.exp)
        q, r = divmod(op1.int, op2.int)
        # remainder is r*10**ideal_exponent; other is +/-op2.int *
        # 10**ideal_exponent.   Apply correction to ensure that
        # abs(remainder) <= abs(other)/2
        if 2*r + (q&1) > op2.int:
            r -= op2.int
            q += 1

        if q >= 10**context.prec:
            return context._raise_error(DivisionImpossible)

        # result has same sign as self unless r is negative
        sign = self._sign
        if r < 0:
            sign = 1-sign
            r = -r

        ans = _dec_from_triple(sign, str(r), ideal_exponent)
        return ans._fix(context)

    def __floordiv__(self, other, context=None):
        """self // other"""
        other = _convert_other(other)
        if other is NotImplemented:
            return other

        if context is None:
            context = getcontext()

        ans = self._check_nans(other, context)
        if ans:
            return ans

        if self._isinfinity():
            if other._isinfinity():
                return context._raise_error(InvalidOperation, 'INF // INF')
            else:
                return _SignedInfinity[self._sign ^ other._sign]

        if not other:
            if self:
                return context._raise_error(DivisionByZero, 'x // 0',
                                            self._sign ^ other._sign)
            else:
                return context._raise_error(DivisionUndefined, '0 // 0')

        return self._divide(other, context)[0]

    def __rfloordiv__(self, other, context=None):
        """Swaps self/other and returns __floordiv__."""
        other = _convert_other(other)
        if other is NotImplemented:
            return other
        return other.__floordiv__(self, context=context)

    def __float__(self):
        """Float representation."""
        if self._isnan():
            if self.is_snan():
                raise ValueError("Cannot convert signaling NaN to float")
            s = "-nan" if self._sign else "nan"
        else:
            s = str(self)
        return float(s)

    def __int__(self):
        """Converts self to an int, truncating if necessary."""
        if self._is_special:
            if self._isnan():
                raise ValueError("Cannot convert NaN to integer")
            elif self._isinfinity():
                raise OverflowError("Cannot convert infinity to integer")
        s = (-1)**self._sign
        if self._exp >= 0:
            return s*int(self._int)*10**self._exp
        else:
            return s*int(self._int[:self._exp] or '0')

    __trunc__ = __int__

    @property
    def real(self):
        return self

    @property
    def imag(self):
        return Decimal(0)

    def conjugate(self):
        return self

    def __complex__(self):
        return complex(float(self))

    def _fix_nan(self, context):
        """Decapitate the payload of a NaN to fit the context"""
        payload = self._int

        # maximum length of payload is precision if clamp=0,
        # precision-1 if clamp=1.
        max_payload_len = context.prec - context.clamp
        if len(payload) > max_payload_len:
            payload = payload[len(payload)-max_payload_len:].lstrip('0')
            return _dec_from_triple(self._sign, payload, self._exp, True)
        return Decimal(self)

    def _fix(self, context):
        """Round if it is necessary to keep self within prec precision.

        Rounds and fixes the exponent.  Does not raise on a sNaN.

        Arguments:
        self - Decimal instance
        context - context used.
        """

        if self._is_special:
            if self._isnan():
                # decapitate payload if necessary
                return self._fix_nan(context)
            else:
                # self is +/-Infinity; return unaltered
                return Decimal(self)

        # if self is zero then exponent should be between Etiny and
        # Emax if clamp==0, and between Etiny and Etop if clamp==1.
        Etiny = context.Etiny()
        Etop = context.Etop()
        if not self:
            exp_max = [context.Emax, Etop][context.clamp]
            new_exp = min(max(self._exp, Etiny), exp_max)
            if new_exp != self._exp:
                context._raise_error(Clamped)
                return _dec_from_triple(self._sign, '0', new_exp)
            else:
                return Decimal(self)

        # exp_min is the smallest allowable exponent of the result,
        # equal to max(self.adjusted()-context.prec+1, Etiny)
        exp_min = len(self._int) + self._exp - context.prec
        if exp_min > Etop:
            # overflow: exp_min > Etop iff self.adjusted() > Emax
            ans = context._raise_error(Overflow, 'above Emax', self._sign)
            context._raise_error(Inexact)
            context._raise_error(Rounded)
            return ans

        self_is_subnormal = exp_min < Etiny
        if self_is_subnormal:
            exp_min = Etiny

        # round if self has too many digits
        if self._exp < exp_min:
            digits = len(self._int) + self._exp - exp_min
            if digits < 0:
                self = _dec_from_triple(self._sign, '1', exp_min-1)
                digits = 0
            rounding_method = self._pick_rounding_function[context.rounding]
            changed = rounding_method(self, digits)
            coeff = self._int[:digits] or '0'
            if changed > 0:
                coeff = str(int(coeff)+1)
                if len(coeff) > context.prec:
                    coeff = coeff[:-1]
                    exp_min += 1

            # check whether the rounding pushed the exponent out of range
            if exp_min > Etop:
                ans = context._raise_error(Overflow, 'above Emax', self._sign)
            else:
                ans = _dec_from_triple(self._sign, coeff, exp_min)

            # raise the appropriate signals, taking care to respect
            # the precedence described in the specification
            if changed and self_is_subnormal:
                context._raise_error(Underflow)
            if self_is_subnormal:
                context._raise_error(Subnormal)
            if changed:
                context._raise_error(Inexact)
            context._raise_error(Rounded)
            if not ans:
                # raise Clamped on underflow to 0
                context._raise_error(Clamped)
            return ans

        if self_is_subnormal:
            context._raise_error(Subnormal)

        # fold down if clamp == 1 and self has too few digits
        if context.clamp == 1 and self._exp > Etop:
            context._raise_error(Clamped)
            self_padded = self._int + '0'*(self._exp - Etop)
            return _dec_from_triple(self._sign, self_padded, Etop)

        # here self was representable to begin with; return unchanged
        return Decimal(self)

    # for each of the rounding functions below:
    #   self is a finite, nonzero Decimal
    #   prec is an integer satisfying 0 <= prec < len(self._int)
    #
    # each function returns either -1, 0, or 1, as follows:
    #   1 indicates that self should be rounded up (away from zero)
    #   0 indicates that self should be truncated, and that all the
    #     digits to be truncated are zeros (so the value is unchanged)
    #  -1 indicates that there are nonzero digits to be truncated

    def _round_down(self, prec):
        """Also known as round-towards-0, truncate."""
        if _all_zeros(self._int, prec):
            return 0
        else:
            return -1

    def _round_up(self, prec):
        """Rounds away from 0."""
        return -self._round_down(prec)

    def _round_half_up(self, prec):
        """Rounds 5 up (away from 0)"""
        if self._int[prec] in '56789':
            return 1
        elif _all_zeros(self._int, prec):
            return 0
        else:
            return -1

    def _round_half_down(self, prec):
        """Round 5 down"""
        if _exact_half(self._int, prec):
            return -1
        else:
            return self._round_half_up(prec)

    def _round_half_even(self, prec):
        """Round 5 to even, rest to nearest."""
        if _exact_half(self._int, prec) and \
                (prec == 0 or self._int[prec-1] in '02468'):
            return -1
        else:
            return self._round_half_up(prec)

    def _round_ceiling(self, prec):
        """Rounds up (not away from 0 if negative.)"""
        if self._sign:
            return self._round_down(prec)
        else:
            return -self._round_down(prec)

    def _round_floor(self, prec):
        """Rounds down (not towards 0 if negative)"""
        if not self._sign:
            return self._round_down(prec)
        else:
            return -self._round_down(prec)

    def _round_05up(self, prec):
        """Round down unless digit prec-1 is 0 or 5."""
        if prec and self._int[prec-1] not in '05':
            return self._round_down(prec)
        else:
            return -self._round_down(prec)

    _pick_rounding_function = dict(
        ROUND_DOWN = _round_down,
        ROUND_UP = _round_up,
        ROUND_HALF_UP = _round_half_up,
        ROUND_HALF_DOWN = _round_half_down,
        ROUND_HALF_EVEN = _round_half_even,
        ROUND_CEILING = _round_ceiling,
        ROUND_FLOOR = _round_floor,
        ROUND_05UP = _round_05up,
    )

    def __round__(self, n=None):
        """Round self to the nearest integer, or to a given precision.

        If only one argument is supplied, round a finite Decimal
        instance self to the nearest integer.  If self is infinite or
        a NaN then a Python exception is raised.  If self is finite
        and lies exactly halfway between two integers then it is
        rounded to the integer with even last digit.

        >>> round(Decimal('123.456'))
        123
        >>> round(Decimal('-456.789'))
        -457
        >>> round(Decimal('-3.0'))
        -3
        >>> round(Decimal('2.5'))
        2
        >>> round(Decimal('3.5'))
        4
        >>> round(Decimal('Inf'))
        Traceback (most recent call last):
          ...
        OverflowError: cannot round an infinity
        >>> round(Decimal('NaN'))
        Traceback (most recent call last):
          ...
        ValueError: cannot round a NaN

        If a second argument n is supplied, self is rounded to n
        decimal places using the rounding mode for the current
        context.

        For an integer n, round(self, -n) is exactly equivalent to
        self.quantize(Decimal('1En')).

        >>> round(Decimal('123.456'), 0)
        Decimal('123')
        >>> round(Decimal('123.456'), 2)
        Decimal('123.46')
        >>> round(Decimal('123.456'), -2)
        Decimal('1E+2')
        >>> round(Decimal('-Infinity'), 37)
        Decimal('NaN')
        >>> round(Decimal('sNaN123'), 0)
        Decimal('NaN123')

        """
        if n is not None:
            # two-argument form: use the equivalent quantize call
            if not isinstance(n, int):
                raise TypeError('Second argument to round should be integral')
            exp = _dec_from_triple(0, '1', -n)
            return self.quantize(exp)

        # one-argument form
        if self._is_special:
            if self.is_nan():
                raise ValueError("cannot round a NaN")
            else:
                raise OverflowError("cannot round an infinity")
        return int(self._rescale(0, ROUND_HALF_EVEN))

    def __floor__(self):
        """Return the floor of self, as an integer.

        For a finite Decimal instance self, return the greatest
        integer n such that n <= self.  If self is infinite or a NaN
        then a Python exception is raised.

        """
        if self._is_special:
            if self.is_nan():
                raise ValueError("cannot round a NaN")
            else:
                raise OverflowError("cannot round an infinity")
        return int(self._rescale(0, ROUND_FLOOR))

    def __ceil__(self):
        """Return the ceiling of self, as an integer.

        For a finite Decimal instance self, return the least integer n
        such that n >= self.  If self is infinite or a NaN then a
        Python exception is raised.

        """
        if self._is_special:
            if self.is_nan():
                raise ValueError("cannot round a NaN")
            else:
                raise OverflowError("cannot round an infinity")
        return int(self._rescale(0, ROUND_CEILING))

    def fma(self, other, third, context=None):
        """Fused multiply-add.

        Returns self*other+third with no rounding of the intermediate
        product self*other.

        self and other are multiplied together, with no rounding of
        the result.  The third operand is then added to the result,
        and a single final rounding is performed.
        """

        other = _convert_other(other, raiseit=True)
        third = _convert_other(third, raiseit=True)

        # compute product; raise InvalidOperation if either operand is
        # a signaling NaN or if the product is zero times infinity.
        if self._is_special or other._is_special:
            if context is None:
                context = getcontext()
            if self._exp == 'N':
                return context._raise_error(InvalidOperation, 'sNaN', self)
            if other._exp == 'N':
                return context._raise_error(InvalidOperation, 'sNaN', other)
            if self._exp == 'n':
                product = self
            elif other._exp == 'n':
                product = other
            elif self._exp == 'F':
                if not other:
                    return context._raise_error(InvalidOperation,
                                                'INF * 0 in fma')
                product = _SignedInfinity[self._sign ^ other._sign]
            elif other._exp == 'F':
                if not self:
                    return context._raise_error(InvalidOperation,
                                                '0 * INF in fma')
                product = _SignedInfinity[self._sign ^ other._sign]
        else:
            product = _dec_from_triple(self._sign ^ other._sign,
                                       str(int(self._int) * int(other._int)),
                                       self._exp + other._exp)

        return product.__add__(third, context)

    def _power_modulo(self, other, modulo, context=None):
        """Three argument version of __pow__"""

        other = _convert_other(other)
        if other is NotImplemented:
            return other
        modulo = _convert_other(modulo)
        if modulo is NotImplemented:
            return modulo

        if context is None:
            context = getcontext()

        # deal with NaNs: if there are any sNaNs then first one wins,
        # (i.e. behaviour for NaNs is identical to that of fma)
        self_is_nan = self._isnan()
        other_is_nan = other._isnan()
        modulo_is_nan = modulo._isnan()
        if self_is_nan or other_is_nan or modulo_is_nan:
            if self_is_nan == 2:
                return context._raise_error(InvalidOperation, 'sNaN',
                                        self)
            if other_is_nan == 2:
                return context._raise_error(InvalidOperation, 'sNaN',
                                        other)
            if modulo_is_nan == 2:
                return context._raise_error(InvalidOperation, 'sNaN',
                                        modulo)
            if self_is_nan:
                return self._fix_nan(context)
            if other_is_nan:
                return other._fix_nan(context)
            return modulo._fix_nan(context)

        # check inputs: we apply same restrictions as Python's pow()
        if not (self._isinteger() and
                other._isinteger() and
                modulo._isinteger()):
            return context._raise_error(InvalidOperation,
                                        'pow() 3rd argument not allowed '
                                        'unless all arguments are integers')
        if other < 0:
            return context._raise_error(InvalidOperation,
                                        'pow() 2nd argument cannot be '
                                        'negative when 3rd argument specified')
        if not modulo:
            return context._raise_error(InvalidOperation,
                                        'pow() 3rd argument cannot be 0')

        # additional restriction for decimal: the modulus must be less
        # than 10**prec in absolute value
        if modulo.adjusted() >= context.prec:
            return context._raise_error(InvalidOperation,
                                        'insufficient precision: pow() 3rd '
                                        'argument must not have more than '
                                        'precision digits')

        # define 0**0 == NaN, for consistency with two-argument pow
        # (even though it hurts!)
        if not other and not self:
            return context._raise_error(InvalidOperation,
                                        'at least one of pow() 1st argument '
                                        'and 2nd argument must be nonzero; '
                                        '0**0 is not defined')

        # compute sign of result
        if other._iseven():
            sign = 0
        else:
            sign = self._sign

        # convert modulo to a Python integer, and self and other to
        # Decimal integers (i.e. force their exponents to be >= 0)
        modulo = abs(int(modulo))
        base = _WorkRep(self.to_integral_value())
        exponent = _WorkRep(other.to_integral_value())

        # compute result using integer pow()
        base = (base.int % modulo * pow(10, base.exp, modulo)) % modulo
        for i in range(exponent.exp):
            base = pow(base, 10, modulo)
        base = pow(base, exponent.int, modulo)

        return _dec_from_triple(sign, str(base), 0)

    def _power_exact(self, other, p):
        """Attempt to compute self**other exactly.

        Given Decimals self and other and an integer p, attempt to
        compute an exact result for the power self**other, with p
        digits of precision.  Return None if self**other is not
        exactly representable in p digits.

        Assumes that elimination of special cases has already been
        performed: self and other must both be nonspecial; self must
        be positive and not numerically equal to 1; other must be
        nonzero.  For efficiency, other._exp should not be too large,
        so that 10**abs(other._exp) is a feasible calculation."""

        # In the comments below, we write x for the value of self and y for the
        # value of other.  Write x = xc*10**xe and abs(y) = yc*10**ye, with xc
        # and yc positive integers not divisible by 10.

        # The main purpose of this method is to identify the *failure*
        # of x**y to be exactly representable with as little effort as
        # possible.  So we look for cheap and easy tests that
        # eliminate the possibility of x**y being exact.  Only if all
        # these tests are passed do we go on to actually compute x**y.

        # Here's the main idea.  Express y as a rational number m/n, with m and
        # n relatively prime and n>0.  Then for x**y to be exactly
        # representable (at *any* precision), xc must be the nth power of a
        # positive integer and xe must be divisible by n.  If y is negative
        # then additionally xc must be a power of either 2 or 5, hence a power
        # of 2**n or 5**n.
        #
        # There's a limit to how small |y| can be: if y=m/n as above
        # then:
        #
        #  (1) if xc != 1 then for the result to be representable we
        #      need xc**(1/n) >= 2, and hence also xc**|y| >= 2.  So
        #      if |y| <= 1/nbits(xc) then xc < 2**nbits(xc) <=
        #      2**(1/|y|), hence xc**|y| < 2 and the result is not
        #      representable.
        #
        #  (2) if xe != 0, |xe|*(1/n) >= 1, so |xe|*|y| >= 1.  Hence if
        #      |y| < 1/|xe| then the result is not representable.
        #
        # Note that since x is not equal to 1, at least one of (1) and
        # (2) must apply.  Now |y| < 1/nbits(xc) iff |yc|*nbits(xc) <
        # 10**-ye iff len(str(|yc|*nbits(xc)) <= -ye.
        #
        # There's also a limit to how large y can be, at least if it's
        # positive: the normalized result will have coefficient xc**y,
        # so if it's representable then xc**y < 10**p, and y <
        # p/log10(xc).  Hence if y*log10(xc) >= p then the result is
        # not exactly representable.

        # if len(str(abs(yc*xe)) <= -ye then abs(yc*xe) < 10**-ye,
        # so |y| < 1/xe and the result is not representable.
        # Similarly, len(str(abs(yc)*xc_bits)) <= -ye implies |y|
        # < 1/nbits(xc).

        x = _WorkRep(self)
        xc, xe = x.int, x.exp
        while xc % 10 == 0:
            xc //= 10
            xe += 1

        y = _WorkRep(other)
        yc, ye = y.int, y.exp
        while yc % 10 == 0:
            yc //= 10
            ye += 1

        # case where xc == 1: result is 10**(xe*y), with xe*y
        # required to be an integer
        if xc == 1:
            xe *= yc
            # result is now 10**(xe * 10**ye);  xe * 10**ye must be integral
            while xe % 10 == 0:
                xe //= 10
                ye += 1
            if ye < 0:
                return None
            exponent = xe * 10**ye
            if y.sign == 1:
                exponent = -exponent
            # if other is a nonnegative integer, use ideal exponent
            if other._isinteger() and other._sign == 0:
                ideal_exponent = self._exp*int(other)
                zeros = min(exponent-ideal_exponent, p-1)
            else:
                zeros = 0
            return _dec_from_triple(0, '1' + '0'*zeros, exponent-zeros)

        # case where y is negative: xc must be either a power
        # of 2 or a power of 5.
        if y.sign == 1:
            last_digit = xc % 10
            if last_digit in (2,4,6,8):
                # quick test for power of 2
                if xc & -xc != xc:
                    return None
                # now xc is a power of 2; e is its exponent
                e = _nbits(xc)-1

                # We now have:
                #
                #   x = 2**e * 10**xe, e > 0, and y < 0.
                #
                # The exact result is:
                #
                #   x**y = 5**(-e*y) * 10**(e*y + xe*y)
                #
                # provided that both e*y and xe*y are integers.  Note that if
                # 5**(-e*y) >= 10**p, then the result can't be expressed
                # exactly with p digits of precision.
                #
                # Using the above, we can guard against large values of ye.
                # 93/65 is an upper bound for log(10)/log(5), so if
                #
                #   ye >= len(str(93*p//65))
                #
                # then
                #
                #   -e*y >= -y >= 10**ye > 93*p/65 > p*log(10)/log(5),
                #
                # so 5**(-e*y) >= 10**p, and the coefficient of the result
                # can't be expressed in p digits.

                # emax >= largest e such that 5**e < 10**p.
                emax = p*93//65
                if ye >= len(str(emax)):
                    return None

                # Find -e*y and -xe*y; both must be integers
                e = _decimal_lshift_exact(e * yc, ye)
                xe = _decimal_lshift_exact(xe * yc, ye)
                if e is None or xe is None:
                    return None

                if e > emax:
                    return None
                xc = 5**e

            elif last_digit == 5:
                # e >= log_5(xc) if xc is a power of 5; we have
                # equality all the way up to xc=5**2658
                e = _nbits(xc)*28//65
                xc, remainder = divmod(5**e, xc)
                if remainder:
                    return None
                while xc % 5 == 0:
                    xc //= 5
                    e -= 1

                # Guard against large values of ye, using the same logic as in
                # the 'xc is a power of 2' branch.  10/3 is an upper bound for
                # log(10)/log(2).
                emax = p*10//3
                if ye >= len(str(emax)):
                    return None

                e = _decimal_lshift_exact(e * yc, ye)
                xe = _decimal_lshift_exact(xe * yc, ye)
                if e is None or xe is None:
                    return None

                if e > emax:
                    return None
                xc = 2**e
            else:
                return None

            if xc >= 10**p:
                return None
            xe = -e-xe
            return _dec_from_triple(0, str(xc), xe)

        # now y is positive; find m and n such that y = m/n
        if ye >= 0:
            m, n = yc*10**ye, 1
        else:
            if xe != 0 and len(str(abs(yc*xe))) <= -ye:
                return None
            xc_bits = _nbits(xc)
            if len(str(abs(yc)*xc_bits)) <= -ye:
                return None
            m, n = yc, 10**(-ye)
            while m % 2 == n % 2 == 0:
                m //= 2
                n //= 2
            while m % 5 == n % 5 == 0:
                m //= 5
                n //= 5

        # compute nth root of xc*10**xe
        if n > 1:
            # if 1 < xc < 2**n then xc isn't an nth power
            if xc_bits <= n:
                return None

            xe, rem = divmod(xe, n)
            if rem != 0:
                return None

            # compute nth root of xc using Newton's method
            a = 1 << -(-_nbits(xc)//n) # initial estimate
            while True:
                q, r = divmod(xc, a**(n-1))
                if a <= q:
                    break
                else:
                    a = (a*(n-1) + q)//n
            if not (a == q and r == 0):
                return None
            xc = a

        # now xc*10**xe is the nth root of the original xc*10**xe
        # compute mth power of xc*10**xe

        # if m > p*100//_log10_lb(xc) then m > p/log10(xc), hence xc**m >
        # 10**p and the result is not representable.
        if xc > 1 and m > p*100//_log10_lb(xc):
            return None
        xc = xc**m
        xe *= m
        if xc > 10**p:
            return None

        # by this point the result *is* exactly representable
        # adjust the exponent to get as close as possible to the ideal
        # exponent, if necessary
        str_xc = str(xc)
        if other._isinteger() and other._sign == 0:
            ideal_exponent = self._exp*int(other)
            zeros = min(xe-ideal_exponent, p-len(str_xc))
        else:
            zeros = 0
        return _dec_from_triple(0, str_xc+'0'*zeros, xe-zeros)

    def __pow__(self, other, modulo=None, context=None):
        """Return self ** other [ % modulo].

        With two arguments, compute self**other.

        With three arguments, compute (self**other) % modulo.  For the
        three argument form, the following restrictions on the
        arguments hold:

         - all three arguments must be integral
         - other must be nonnegative
         - either self or other (or both) must be nonzero
         - modulo must be nonzero and must have at most p digits,
           where p is the context precision.

        If any of these restrictions is violated the InvalidOperation
        flag is raised.

        The result of pow(self, other, modulo) is identical to the
        result that would be obtained by computing (self**other) %
        modulo with unbounded precision, but is computed more
        efficiently.  It is always exact.
        """

        if modulo is not None:
            return self._power_modulo(other, modulo, context)

        other = _convert_other(other)
        if other is NotImplemented:
            return other

        if context is None:
            context = getcontext()

        # either argument is a NaN => result is NaN
        ans = self._check_nans(other, context)
        if ans:
            return ans

        # 0**0 = NaN (!), x**0 = 1 for nonzero x (including +/-Infinity)
        if not other:
            if not self:
                return context._raise_error(InvalidOperation, '0 ** 0')
            else:
                return _One

        # result has sign 1 iff self._sign is 1 and other is an odd integer
        result_sign = 0
        if self._sign == 1:
            if other._isinteger():
                if not other._iseven():
                    result_sign = 1
            else:
                # -ve**noninteger = NaN
                # (-0)**noninteger = 0**noninteger
                if self:
                    return context._raise_error(InvalidOperation,
                        'x ** y with x negative and y not an integer')
            # negate self, without doing any unwanted rounding
            self = self.copy_negate()

        # 0**(+ve or Inf)= 0; 0**(-ve or -Inf) = Infinity
        if not self:
            if other._sign == 0:
                return _dec_from_triple(result_sign, '0', 0)
            else:
                return _SignedInfinity[result_sign]

        # Inf**(+ve or Inf) = Inf; Inf**(-ve or -Inf) = 0
        if self._isinfinity():
            if other._sign == 0:
                return _SignedInfinity[result_sign]
            else:
                return _dec_from_triple(result_sign, '0', 0)

        # 1**other = 1, but the choice of exponent and the flags
        # depend on the exponent of self, and on whether other is a
        # positive integer, a negative integer, or neither
        if self == _One:
            if other._isinteger():
                # exp = max(self._exp*max(int(other), 0),
                # 1-context.prec) but evaluating int(other) directly
                # is dangerous until we know other is small (other
                # could be 1e999999999)
                if other._sign == 1:
                    multiplier = 0
                elif other > context.prec:
                    multiplier = context.prec
                else:
                    multiplier = int(other)

                exp = self._exp * multiplier
                if exp < 1-context.prec:
                    exp = 1-context.prec
                    context._raise_error(Rounded)
            else:
                context._raise_error(Inexact)
                context._raise_error(Rounded)
                exp = 1-context.prec

            return _dec_from_triple(result_sign, '1'+'0'*-exp, exp)

        # compute adjusted exponent of self
        self_adj = self.adjusted()

        # self ** infinity is infinity if self > 1, 0 if self < 1
        # self ** -infinity is infinity if self < 1, 0 if self > 1
        if other._isinfinity():
            if (other._sign == 0) == (self_adj < 0):
                return _dec_from_triple(result_sign, '0', 0)
            else:
                return _SignedInfinity[result_sign]

        # from here on, the result always goes through the call
        # to _fix at the end of this function.
        ans = None
        exact = False

        # crude test to catch cases of extreme overflow/underflow.  If
        # log10(self)*other >= 10**bound and bound >= len(str(Emax))
        # then 10**bound >= 10**len(str(Emax)) >= Emax+1 and hence
        # self**other >= 10**(Emax+1), so overflow occurs.  The test
        # for underflow is similar.
        bound = self._log10_exp_bound() + other.adjusted()
        if (self_adj >= 0) == (other._sign == 0):
            # self > 1 and other +ve, or self < 1 and other -ve
            # possibility of overflow
            if bound >= len(str(context.Emax)):
                ans = _dec_from_triple(result_sign, '1', context.Emax+1)
        else:
            # self > 1 and other -ve, or self < 1 and other +ve
            # possibility of underflow to 0
            Etiny = context.Etiny()
            if bound >= len(str(-Etiny)):
                ans = _dec_from_triple(result_sign, '1', Etiny-1)

        # try for an exact result with precision +1
        if ans is None:
            ans = self._power_exact(other, context.prec + 1)
            if ans is not None:
                if result_sign == 1:
                    ans = _dec_from_triple(1, ans._int, ans._exp)
                exact = True

        # usual case: inexact result, x**y computed directly as exp(y*log(x))
        if ans is None:
            p = context.prec
            x = _WorkRep(self)
            xc, xe = x.int, x.exp
            y = _WorkRep(other)
            yc, ye = y.int, y.exp
            if y.sign == 1:
                yc = -yc

            # compute correctly rounded result:  start with precision +3,
            # then increase precision until result is unambiguously roundable
            extra = 3
            while True:
                coeff, exp = _dpower(xc, xe, yc, ye, p+extra)
                if coeff % (5*10**(len(str(coeff))-p-1)):
                    break
                extra += 3

            ans = _dec_from_triple(result_sign, str(coeff), exp)

        # unlike exp, ln and log10, the power function respects the
        # rounding mode; no need to switch to ROUND_HALF_EVEN here

        # There's a difficulty here when 'other' is not an integer and
        # the result is exact.  In this case, the specification
        # requires that the Inexact flag be raised (in spite of
        # exactness), but since the result is exact _fix won't do this
        # for us.  (Correspondingly, the Underflow signal should also
        # be raised for subnormal results.)  We can't directly raise
        # these signals either before or after calling _fix, since
        # that would violate the precedence for signals.  So we wrap
        # the ._fix call in a temporary context, and reraise
        # afterwards.
        if exact and not other._isinteger():
            # pad with zeros up to length context.prec+1 if necessary; this
            # ensures that the Rounded signal will be raised.
            if len(ans._int) <= context.prec:
                expdiff = context.prec + 1 - len(ans._int)
                ans = _dec_from_triple(ans._sign, ans._int+'0'*expdiff,
                                       ans._exp-expdiff)

            # create a copy of the current context, with cleared flags/traps
            newcontext = context.copy()
            newcontext.clear_flags()
            for exception in _signals:
                newcontext.traps[exception] = 0

            # round in the new context
            ans = ans._fix(newcontext)

            # raise Inexact, and if necessary, Underflow
            newcontext._raise_error(Inexact)
            if newcontext.flags[Subnormal]:
                newcontext._raise_error(Underflow)

            # propagate signals to the original context; _fix could
            # have raised any of Overflow, Underflow, Subnormal,
            # Inexact, Rounded, Clamped.  Overflow needs the correct
            # arguments.  Note that the order of the exceptions is
            # important here.
            if newcontext.flags[Overflow]:
                context._raise_error(Overflow, 'above Emax', ans._sign)
            for exception in Underflow, Subnormal, Inexact, Rounded, Clamped:
                if newcontext.flags[exception]:
                    context._raise_error(exception)

        else:
            ans = ans._fix(context)

        return ans

    def __rpow__(self, other, context=None):
        """Swaps self/other and returns __pow__."""
        other = _convert_other(other)
        if other is NotImplemented:
            return other
        return other.__pow__(self, context=context)

    def normalize(self, context=None):
        """Normalize- strip trailing 0s, change anything equal to 0 to 0e0"""

        if context is None:
            context = getcontext()

        if self._is_special:
            ans = self._check_nans(context=context)
            if ans:
                return ans

        dup = self._fix(context)
        if dup._isinfinity():
            return dup

        if not dup:
            return _dec_from_triple(dup._sign, '0', 0)
        exp_max = [context.Emax, context.Etop()][context.clamp]
        end = len(dup._int)
        exp = dup._exp
        while dup._int[end-1] == '0' and exp < exp_max:
            exp += 1
            end -= 1
        return _dec_from_triple(dup._sign, dup._int[:end], exp)

    def quantize(self, exp, rounding=None, context=None):
        """Quantize self so its exponent is the same as that of exp.

        Similar to self._rescale(exp._exp) but with error checking.
        """
        exp = _convert_other(exp, raiseit=True)

        if context is None:
            context = getcontext()
        if rounding is None:
            rounding = context.rounding

        if self._is_special or exp._is_special:
            ans = self._check_nans(exp, context)
            if ans:
                return ans

            if exp._isinfinity() or self._isinfinity():
                if exp._isinfinity() and self._isinfinity():
                    return Decimal(self)  # if both are inf, it is OK
                return context._raise_error(InvalidOperation,
                                        'quantize with one INF')

        # exp._exp should be between Etiny and Emax
        if not (context.Etiny() <= exp._exp <= context.Emax):
            return context._raise_error(InvalidOperation,
                   'target exponent out of bounds in quantize')

        if not self:
            ans = _dec_from_triple(self._sign, '0', exp._exp)
            return ans._fix(context)

        self_adjusted = self.adjusted()
        if self_adjusted > context.Emax:
            return context._raise_error(InvalidOperation,
                                        'exponent of quantize result too large for current context')
        if self_adjusted - exp._exp + 1 > context.prec:
            return context._raise_error(InvalidOperation,
                                        'quantize result has too many digits for current context')

        ans = self._rescale(exp._exp, rounding)
        if ans.adjusted() > context.Emax:
            return context._raise_error(InvalidOperation,
                                        'exponent of quantize result too large for current context')
        if len(ans._int) > context.prec:
            return context._raise_error(InvalidOperation,
                                        'quantize result has too many digits for current context')

        # raise appropriate flags
        if ans and ans.adjusted() < context.Emin:
            context._raise_error(Subnormal)
        if ans._exp > self._exp:
            if ans != self:
                context._raise_error(Inexact)
            context._raise_error(Rounded)

        # call to fix takes care of any necessary folddown, and
        # signals Clamped if necessary
        ans = ans._fix(context)
        return ans

    def same_quantum(self, other, context=None):
        """Return True if self and other have the same exponent; otherwise
        return False.

        If either operand is a special value, the following rules are used:
           * return True if both operands are infinities
           * return True if both operands are NaNs
           * otherwise, return False.
        """
        other = _convert_other(other, raiseit=True)
        if self._is_special or other._is_special:
            return (self.is_nan() and other.is_nan() or
                    self.is_infinite() and other.is_infinite())
        return self._exp == other._exp

    def _rescale(self, exp, rounding):
        """Rescale self so that the exponent is exp, either by padding with zeros
        or by truncating digits, using the given rounding mode.

        Specials are returned without change.  This operation is
        quiet: it raises no flags, and uses no information from the
        context.

        exp = exp to scale to (an integer)
        rounding = rounding mode
        """
        if self._is_special:
            return Decimal(self)
        if not self:
            return _dec_from_triple(self._sign, '0', exp)

        if self._exp >= exp:
            # pad answer with zeros if necessary
            return _dec_from_triple(self._sign,
                                        self._int + '0'*(self._exp - exp), exp)

        # too many digits; round and lose data.  If self.adjusted() <
        # exp-1, replace self by 10**(exp-1) before rounding
        digits = len(self._int) + self._exp - exp
        if digits < 0:
            self = _dec_from_triple(self._sign, '1', exp-1)
            digits = 0
        this_function = self._pick_rounding_function[rounding]
        changed = this_function(self, digits)
        coeff = self._int[:digits] or '0'
        if changed == 1:
            coeff = str(int(coeff)+1)
        return _dec_from_triple(self._sign, coeff, exp)

    def _round(self, places, rounding):
        """Round a nonzero, nonspecial Decimal to a fixed number of
        significant figures, using the given rounding mode.

        Infinities, NaNs and zeros are returned unaltered.

        This operation is quiet: it raises no flags, and uses no
        information from the context.

        """
        if places <= 0:
            raise ValueError("argument should be at least 1 in _round")
        if self._is_special or not self:
            return Decimal(self)
        ans = self._rescale(self.adjusted()+1-places, rounding)
        # it can happen that the rescale alters the adjusted exponent;
        # for example when rounding 99.97 to 3 significant figures.
        # When this happens we end up with an extra 0 at the end of
        # the number; a second rescale fixes this.
        if ans.adjusted() != self.adjusted():
            ans = ans._rescale(ans.adjusted()+1-places, rounding)
        return ans

    def to_integral_exact(self, rounding=None, context=None):
        """Rounds to a nearby integer.

        If no rounding mode is specified, take the rounding mode from
        the context.  This method raises the Rounded and Inexact flags
        when appropriate.

        See also: to_integral_value, which does exactly the same as
        this method except that it doesn't raise Inexact or Rounded.
        """
        if self._is_special:
            ans = self._check_nans(context=context)
            if ans:
                return ans
            return Decimal(self)
        if self._exp >= 0:
            return Decimal(self)
        if not self:
            return _dec_from_triple(self._sign, '0', 0)
        if context is None:
            context = getcontext()
        if rounding is None:
            rounding = context.rounding
        ans = self._rescale(0, rounding)
        if ans != self:
            context._raise_error(Inexact)
        context._raise_error(Rounded)
        return ans

    def to_integral_value(self, rounding=None, context=None):
        """Rounds to the nearest integer, without raising inexact, rounded."""
        if context is None:
            context = getcontext()
        if rounding is None:
            rounding = context.rounding
        if self._is_special:
            ans = self._check_nans(context=context)
            if ans:
                return ans
            return Decimal(self)
        if self._exp >= 0:
            return Decimal(self)
        else:
            return self._rescale(0, rounding)

    # the method name changed, but we provide also the old one, for compatibility
    to_integral = to_integral_value

    def sqrt(self, context=None):
        """Return the square root of self."""
        if context is None:
            context = getcontext()

        if self._is_special:
            ans = self._check_nans(context=context)
            if ans:
                return ans

            if self._isinfinity() and self._sign == 0:
                return Decimal(self)

        if not self:
            # exponent = self._exp // 2.  sqrt(-0) = -0
            ans = _dec_from_triple(self._sign, '0', self._exp // 2)
            return ans._fix(context)

        if self._sign == 1:
            return context._raise_error(InvalidOperation, 'sqrt(-x), x > 0')

        # At this point self represents a positive number.  Let p be
        # the desired precision and express self in the form c*100**e
        # with c a positive real number and e an integer, c and e
        # being chosen so that 100**(p-1) <= c < 100**p.  Then the
        # (exact) square root of self is sqrt(c)*10**e, and 10**(p-1)
        # <= sqrt(c) < 10**p, so the closest representable Decimal at
        # precision p is n*10**e where n = round_half_even(sqrt(c)),
        # the closest integer to sqrt(c) with the even integer chosen
        # in the case of a tie.
        #
        # To ensure correct rounding in all cases, we use the
        # following trick: we compute the square root to an extra
        # place (precision p+1 instead of precision p), rounding down.
        # Then, if the result is inexact and its last digit is 0 or 5,
        # we increase the last digit to 1 or 6 respectively; if it's
        # exact we leave the last digit alone.  Now the final round to
        # p places (or fewer in the case of underflow) will round
        # correctly and raise the appropriate flags.

        # use an extra digit of precision
        prec = context.prec+1

        # write argument in the form c*100**e where e = self._exp//2
        # is the 'ideal' exponent, to be used if the square root is
        # exactly representable.  l is the number of 'digits' of c in
        # base 100, so that 100**(l-1) <= c < 100**l.
        op = _WorkRep(self)
        e = op.exp >> 1
        if op.exp & 1:
            c = op.int * 10
            l = (len(self._int) >> 1) + 1
        else:
            c = op.int
            l = len(self._int)+1 >> 1

        # rescale so that c has exactly prec base 100 'digits'
        shift = prec-l
        if shift >= 0:
            c *= 100**shift
            exact = True
        else:
            c, remainder = divmod(c, 100**-shift)
            exact = not remainder
        e -= shift

        # find n = floor(sqrt(c)) using Newton's method
        n = 10**prec
        while True:
            q = c//n
            if n <= q:
                break
            else:
                n = n + q >> 1
        exact = exact and n*n == c

        if exact:
            # result is exact; rescale to use ideal exponent e
            if shift >= 0:
                # assert n % 10**shift == 0
                n //= 10**shift
            else:
                n *= 10**-shift
            e += shift
        else:
            # result is not exact; fix last digit as described above
            if n % 5 == 0:
                n += 1

        ans = _dec_from_triple(0, str(n), e)

        # round, and fit to current context
        context = context._shallow_copy()
        rounding = context._set_rounding(ROUND_HALF_EVEN)
        ans = ans._fix(context)
        context.rounding = rounding

        return ans

    def max(self, other, context=None):
        """Returns the larger value.

        Like max(self, other) except if one is not a number, returns
        NaN (and signals if one is sNaN).  Also rounds.
        """
        other = _convert_other(other, raiseit=True)

        if context is None:
            context = getcontext()

        if self._is_special or other._is_special:
            # If one operand is a quiet NaN and the other is number, then the
            # number is always returned
            sn = self._isnan()
            on = other._isnan()
            if sn or on:
                if on == 1 and sn == 0:
                    return self._fix(context)
                if sn == 1 and on == 0:
                    return other._fix(context)
                return self._check_nans(other, context)

        c = self._cmp(other)
        if c == 0:
            # If both operands are finite and equal in numerical value
            # then an ordering is applied:
            #
            # If the signs differ then max returns the operand with the
            # positive sign and min returns the operand with the negative sign
            #
            # If the signs are the same then the exponent is used to select
            # the result.  This is exactly the ordering used in compare_total.
            c = self.compare_total(other)

        if c == -1:
            ans = other
        else:
            ans = self

        return ans._fix(context)

    def min(self, other, context=None):
        """Returns the smaller value.

        Like min(self, other) except if one is not a number, returns
        NaN (and signals if one is sNaN).  Also rounds.
        """
        other = _convert_other(other, raiseit=True)

        if context is None:
            context = getcontext()

        if self._is_special or other._is_special:
            # If one operand is a quiet NaN and the other is number, then the
            # number is always returned
            sn = self._isnan()
            on = other._isnan()
            if sn or on:
                if on == 1 and sn == 0:
                    return self._fix(context)
                if sn == 1 and on == 0:
                    return other._fix(context)
                return self._check_nans(other, context)

        c = self._cmp(other)
        if c == 0:
            c = self.compare_total(other)

        if c == -1:
            ans = self
        else:
            ans = other

        return ans._fix(context)

    def _isinteger(self):
        """Returns whether self is an integer"""
        if self._is_special:
            return False
        if self._exp >= 0:
            return True
        rest = self._int[self._exp:]
        return rest == '0'*len(rest)

    def _iseven(self):
        """Returns True if self is even.  Assumes self is an integer."""
        if not self or self._exp > 0:
            return True
        return self._int[-1+self._exp] in '02468'

    def adjusted(self):
        """Return the adjusted exponent of self"""
        try:
            return self._exp + len(self._int) - 1
        # If NaN or Infinity, self._exp is string
        except TypeError:
            return 0

    def canonical(self):
        """Returns the same Decimal object.

        As we do not have different encodings for the same number, the
        received object already is in its canonical form.
        """
        return self

    def compare_signal(self, other, context=None):
        """Compares self to the other operand numerically.

        It's pretty much like compare(), but all NaNs signal, with signaling
        NaNs taking precedence over quiet NaNs.
        """
        other = _convert_other(other, raiseit = True)
        ans = self._compare_check_nans(other, context)
        if ans:
            return ans
        return self.compare(other, context=context)

    def compare_total(self, other, context=None):
        """Compares self to other using the abstract representations.

        This is not like the standard compare, which use their numerical
        value. Note that a total ordering is defined for all possible abstract
        representations.
        """
        other = _convert_other(other, raiseit=True)

        # if one is negative and the other is positive, it's easy
        if self._sign and not other._sign:
            return _NegativeOne
        if not self._sign and other._sign:
            return _One
        sign = self._sign

        # let's handle both NaN types
        self_nan = self._isnan()
        other_nan = other._isnan()
        if self_nan or other_nan:
            if self_nan == other_nan:
                # compare payloads as though they're integers
                self_key = len(self._int), self._int
                other_key = len(other._int), other._int
                if self_key < other_key:
                    if sign:
                        return _One
                    else:
                        return _NegativeOne
                if self_key > other_key:
                    if sign:
                        return _NegativeOne
                    else:
                        return _One
                return _Zero

            if sign:
                if self_nan == 1:
                    return _NegativeOne
                if other_nan == 1:
                    return _One
                if self_nan == 2:
                    return _NegativeOne
                if other_nan == 2:
                    return _One
            else:
                if self_nan == 1:
                    return _One
                if other_nan == 1:
                    return _NegativeOne
                if self_nan == 2:
                    return _One
                if other_nan == 2:
                    return _NegativeOne

        if self < other:
            return _NegativeOne
        if self > other:
            return _One

        if self._exp < other._exp:
            if sign:
                return _One
            else:
                return _NegativeOne
        if self._exp > other._exp:
            if sign:
                return _NegativeOne
            else:
                return _One
        return _Zero


    def compare_total_mag(self, other, context=None):
        """Compares self to other using abstract repr., ignoring sign.

        Like compare_total, but with operand's sign ignored and assumed to be 0.
        """
        other = _convert_other(other, raiseit=True)

        s = self.copy_abs()
        o = other.copy_abs()
        return s.compare_total(o)

    def copy_abs(self):
        """Returns a copy with the sign set to 0. """
        return _dec_from_triple(0, self._int, self._exp, self._is_special)

    def copy_negate(self):
        """Returns a copy with the sign inverted."""
        if self._sign:
            return _dec_from_triple(0, self._int, self._exp, self._is_special)
        else:
            return _dec_from_triple(1, self._int, self._exp, self._is_special)

    def copy_sign(self, other, context=None):
        """Returns self with the sign of other."""
        other = _convert_other(other, raiseit=True)
        return _dec_from_triple(other._sign, self._int,
                                self._exp, self._is_special)

    def exp(self, context=None):
        """Returns e ** self."""

        if context is None:
            context = getcontext()

        # exp(NaN) = NaN
        ans = self._check_nans(context=context)
        if ans:
            return ans

        # exp(-Infinity) = 0
        if self._isinfinity() == -1:
            return _Zero

        # exp(0) = 1
        if not self:
            return _One

        # exp(Infinity) = Infinity
        if self._isinfinity() == 1:
            return Decimal(self)

        # the result is now guaranteed to be inexact (the true
        # mathematical result is transcendental). There's no need to
        # raise Rounded and Inexact here---they'll always be raised as
        # a result of the call to _fix.
        p = context.prec
        adj = self.adjusted()

        # we only need to do any computation for quite a small range
        # of adjusted exponents---for example, -29 <= adj <= 10 for
        # the default context.  For smaller exponent the result is
        # indistinguishable from 1 at the given precision, while for
        # larger exponent the result either overflows or underflows.
        if self._sign == 0 and adj > len(str((context.Emax+1)*3)):
            # overflow
            ans = _dec_from_triple(0, '1', context.Emax+1)
        elif self._sign == 1 and adj > len(str((-context.Etiny()+1)*3)):
            # underflow to 0
            ans = _dec_from_triple(0, '1', context.Etiny()-1)
        elif self._sign == 0 and adj < -p:
            # p+1 digits; final round will raise correct flags
            ans = _dec_from_triple(0, '1' + '0'*(p-1) + '1', -p)
        elif self._sign == 1 and adj < -p-1:
            # p+1 digits; final round will raise correct flags
            ans = _dec_from_triple(0, '9'*(p+1), -p-1)
        # general case
        else:
            op = _WorkRep(self)
            c, e = op.int, op.exp
            if op.sign == 1:
                c = -c

            # compute correctly rounded result: increase precision by
            # 3 digits at a time until we get an unambiguously
            # roundable result
            extra = 3
            while True:
                coeff, exp = _dexp(c, e, p+extra)
                if coeff % (5*10**(len(str(coeff))-p-1)):
                    break
                extra += 3

            ans = _dec_from_triple(0, str(coeff), exp)

        # at this stage, ans should round correctly with *any*
        # rounding mode, not just with ROUND_HALF_EVEN
        context = context._shallow_copy()
        rounding = context._set_rounding(ROUND_HALF_EVEN)
        ans = ans._fix(context)
        context.rounding = rounding

        return ans

    def is_canonical(self):
        """Return True if self is canonical; otherwise return False.

        Currently, the encoding of a Decimal instance is always
        canonical, so this method returns True for any Decimal.
        """
        return True

    def is_finite(self):
        """Return True if self is finite; otherwise return False.

        A Decimal instance is considered finite if it is neither
        infinite nor a NaN.
        """
        return not self._is_special

    def is_infinite(self):
        """Return True if self is infinite; otherwise return False."""
        return self._exp == 'F'

    def is_nan(self):
        """Return True if self is a qNaN or sNaN; otherwise return False."""
        return self._exp in ('n', 'N')

    def is_normal(self, context=None):
        """Return True if self is a normal number; otherwise return False."""
        if self._is_special or not self:
            return False
        if context is None:
            context = getcontext()
        return context.Emin <= self.adjusted()

    def is_qnan(self):
        """Return True if self is a quiet NaN; otherwise return False."""
        return self._exp == 'n'

    def is_signed(self):
        """Return True if self is negative; otherwise return False."""
        return self._sign == 1

    def is_snan(self):
        """Return True if self is a signaling NaN; otherwise return False."""
        return self._exp == 'N'

    def is_subnormal(self, context=None):
        """Return True if self is subnormal; otherwise return False."""
        if self._is_special or not self:
            return False
        if context is None:
            context = getcontext()
        return self.adjusted() < context.Emin

    def is_zero(self):
        """Return True if self is a zero; otherwise return False."""
        return not self._is_special and self._int == '0'

    def _ln_exp_bound(self):
        """Compute a lower bound for the adjusted exponent of self.ln().
        In other words, compute r such that self.ln() >= 10**r.  Assumes
        that self is finite and positive and that self != 1.
        """

        # for 0.1 <= x <= 10 we use the inequalities 1-1/x <= ln(x) <= x-1
        adj = self._exp + len(self._int) - 1
        if adj >= 1:
            # argument >= 10; we use 23/10 = 2.3 as a lower bound for ln(10)
            return len(str(adj*23//10)) - 1
        if adj <= -2:
            # argument <= 0.1
            return len(str((-1-adj)*23//10)) - 1
        op = _WorkRep(self)
        c, e = op.int, op.exp
        if adj == 0:
            # 1 < self < 10
            num = str(c-10**-e)
            den = str(c)
            return len(num) - len(den) - (num < den)
        # adj == -1, 0.1 <= self < 1
        return e + len(str(10**-e - c)) - 1


    def ln(self, context=None):
        """Returns the natural (base e) logarithm of self."""

        if context is None:
            context = getcontext()

        # ln(NaN) = NaN
        ans = self._check_nans(context=context)
        if ans:
            return ans

        # ln(0.0) == -Infinity
        if not self:
            return _NegativeInfinity

        # ln(Infinity) = Infinity
        if self._isinfinity() == 1:
            return _Infinity

        # ln(1.0) == 0.0
        if self == _One:
            return _Zero

        # ln(negative) raises InvalidOperation
        if self._sign == 1:
            return context._raise_error(InvalidOperation,
                                        'ln of a negative value')

        # result is irrational, so necessarily inexact
        op = _WorkRep(self)
        c, e = op.int, op.exp
        p = context.prec

        # correctly rounded result: repeatedly increase precision by 3
        # until we get an unambiguously roundable result
        places = p - self._ln_exp_bound() + 2 # at least p+3 places
        while True:
            coeff = _dlog(c, e, places)
            # assert len(str(abs(coeff)))-p >= 1
            if coeff % (5*10**(len(str(abs(coeff)))-p-1)):
                break
            places += 3
        ans = _dec_from_triple(int(coeff<0), str(abs(coeff)), -places)

        context = context._shallow_copy()
        rounding = context._set_rounding(ROUND_HALF_EVEN)
        ans = ans._fix(context)
        context.rounding = rounding
        return ans

    def _log10_exp_bound(self):
        """Compute a lower bound for the adjusted exponent of self.log10().
        In other words, find r such that self.log10() >= 10**r.
        Assumes that self is finite and positive and that self != 1.
        """

        # For x >= 10 or x < 0.1 we only need a bound on the integer
        # part of log10(self), and this comes directly from the
        # exponent of x.  For 0.1 <= x <= 10 we use the inequalities
        # 1-1/x <= log(x) <= x-1. If x > 1 we have |log10(x)| >
        # (1-1/x)/2.31 > 0.  If x < 1 then |log10(x)| > (1-x)/2.31 > 0

        adj = self._exp + len(self._int) - 1
        if adj >= 1:
            # self >= 10
            return len(str(adj))-1
        if adj <= -2:
            # self < 0.1
            return len(str(-1-adj))-1
        op = _WorkRep(self)
        c, e = op.int, op.exp
        if adj == 0:
            # 1 < self < 10
            num = str(c-10**-e)
            den = str(231*c)
            return len(num) - len(den) - (num < den) + 2
        # adj == -1, 0.1 <= self < 1
        num = str(10**-e-c)
        return len(num) + e - (num < "231") - 1

    def log10(self, context=None):
        """Returns the base 10 logarithm of self."""

        if context is None:
            context = getcontext()

        # log10(NaN) = NaN
        ans = self._check_nans(context=context)
        if ans:
            return ans

        # log10(0.0) == -Infinity
        if not self:
            return _NegativeInfinity

        # log10(Infinity) = Infinity
        if self._isinfinity() == 1:
            return _Infinity

        # log10(negative or -Infinity) raises InvalidOperation
        if self._sign == 1:
            return context._raise_error(InvalidOperation,
                                        'log10 of a negative value')

        # log10(10**n) = n
        if self._int[0] == '1' and self._int[1:] == '0'*(len(self._int) - 1):
            # answer may need rounding
            ans = Decimal(self._exp + len(self._int) - 1)
        else:
            # result is irrational, so necessarily inexact
            op = _WorkRep(self)
            c, e = op.int, op.exp
            p = context.prec

            # correctly rounded result: repeatedly increase precision
            # until result is unambiguously roundable
            places = p-self._log10_exp_bound()+2
            while True:
                coeff = _dlog10(c, e, places)
                # assert len(str(abs(coeff)))-p >= 1
                if coeff % (5*10**(len(str(abs(coeff)))-p-1)):
                    break
                places += 3
            ans = _dec_from_triple(int(coeff<0), str(abs(coeff)), -places)

        context = context._shallow_copy()
        rounding = context._set_rounding(ROUND_HALF_EVEN)
        ans = ans._fix(context)
        context.rounding = rounding
        return ans

    def logb(self, context=None):
        """ Returns the exponent of the magnitude of self's MSD.

        The result is the integer which is the exponent of the magnitude
        of the most significant digit of self (as though it were truncated
        to a single digit while maintaining the value of that digit and
        without limiting the resulting exponent).
        """
        # logb(NaN) = NaN
        ans = self._check_nans(context=context)
        if ans:
            return ans

        if context is None:
            context = getcontext()

        # logb(+/-Inf) = +Inf
        if self._isinfinity():
            return _Infinity

        # logb(0) = -Inf, DivisionByZero
        if not self:
            return context._raise_error(DivisionByZero, 'logb(0)', 1)

        # otherwise, simply return the adjusted exponent of self, as a
        # Decimal.  Note that no attempt is made to fit the result
        # into the current context.
        ans = Decimal(self.adjusted())
        return ans._fix(context)

    def _islogical(self):
        """Return True if self is a logical operand.

        For being logical, it must be a finite number with a sign of 0,
        an exponent of 0, and a coefficient whose digits must all be
        either 0 or 1.
        """
        if self._sign != 0 or self._exp != 0:
            return False
        for dig in self._int:
            if dig not in '01':
                return False
        return True

    def _fill_logical(self, context, opa, opb):
        dif = context.prec - len(opa)
        if dif > 0:
            opa = '0'*dif + opa
        elif dif < 0:
            opa = opa[-context.prec:]
        dif = context.prec - len(opb)
        if dif > 0:
            opb = '0'*dif + opb
        elif dif < 0:
            opb = opb[-context.prec:]
        return opa, opb

    def logical_and(self, other, context=None):
        """Applies an 'and' operation between self and other's digits."""
        if context is None:
            context = getcontext()

        other = _convert_other(other, raiseit=True)

        if not self._islogical() or not other._islogical():
            return context._raise_error(InvalidOperation)

        # fill to context.prec
        (opa, opb) = self._fill_logical(context, self._int, other._int)

        # make the operation, and clean starting zeroes
        result = "".join([str(int(a)&int(b)) for a,b in zip(opa,opb)])
        return _dec_from_triple(0, result.lstrip('0') or '0', 0)

    def logical_invert(self, context=None):
        """Invert all its digits."""
        if context is None:
            context = getcontext()
        return self.logical_xor(_dec_from_triple(0,'1'*context.prec,0),
                                context)

    def logical_or(self, other, context=None):
        """Applies an 'or' operation between self and other's digits."""
        if context is None:
            context = getcontext()

        other = _convert_other(other, raiseit=True)

        if not self._islogical() or not other._islogical():
            return context._raise_error(InvalidOperation)

        # fill to context.prec
        (opa, opb) = self._fill_logical(context, self._int, other._int)

        # make the operation, and clean starting zeroes
        result = "".join([str(int(a)|int(b)) for a,b in zip(opa,opb)])
        return _dec_from_triple(0, result.lstrip('0') or '0', 0)

    def logical_xor(self, other, context=None):
        """Applies an 'xor' operation between self and other's digits."""
        if context is None:
            context = getcontext()

        other = _convert_other(other, raiseit=True)

        if not self._islogical() or not other._islogical():
            return context._raise_error(InvalidOperation)

        # fill to context.prec
        (opa, opb) = self._fill_logical(context, self._int, other._int)

        # make the operation, and clean starting zeroes
        result = "".join([str(int(a)^int(b)) for a,b in zip(opa,opb)])
        return _dec_from_triple(0, result.lstrip('0') or '0', 0)

    def max_mag(self, other, context=None):
        """Compares the values numerically with their sign ignored."""
        other = _convert_other(other, raiseit=True)

        if context is None:
            context = getcontext()

        if self._is_special or other._is_special:
            # If one operand is a quiet NaN and the other is number, then the
            # number is always returned
            sn = self._isnan()
            on = other._isnan()
            if sn or on:
                if on == 1 and sn == 0:
                    return self._fix(context)
                if sn == 1 and on == 0:
                    return other._fix(context)
                return self._check_nans(other, context)

        c = self.copy_abs()._cmp(other.copy_abs())
        if c == 0:
            c = self.compare_total(other)

        if c == -1:
            ans = other
        else:
            ans = self

        return ans._fix(context)

    def min_mag(self, other, context=None):
        """Compares the values numerically with their sign ignored."""
        other = _convert_other(other, raiseit=True)

        if context is None:
            context = getcontext()

        if self._is_special or other._is_special:
            # If one operand is a quiet NaN and the other is number, then the
            # number is always returned
            sn = self._isnan()
            on = other._isnan()
            if sn or on:
                if on == 1 and sn == 0:
                    return self._fix(context)
                if sn == 1 and on == 0:
                    return other._fix(context)
                return self._check_nans(other, context)

        c = self.copy_abs()._cmp(other.copy_abs())
        if c == 0:
            c = self.compare_total(other)

        if c == -1:
            ans = self
        else:
            ans = other

        return ans._fix(context)

    def next_minus(self, context=None):
        """Returns the largest representable number smaller than itself."""
        if context is None:
            context = getcontext()

        ans = self._check_nans(context=context)
        if ans:
            return ans

        if self._isinfinity() == -1:
            return _NegativeInfinity
        if self._isinfinity() == 1:
            return _dec_from_triple(0, '9'*context.prec, context.Etop())

        context = context.copy()
        context._set_rounding(ROUND_FLOOR)
        context._ignore_all_flags()
        new_self = self._fix(context)
        if new_self != self:
            return new_self
        return self.__sub__(_dec_from_triple(0, '1', context.Etiny()-1),
                            context)

    def next_plus(self, context=None):
        """Returns the smallest representable number larger than itself."""
        if context is None:
            context = getcontext()

        ans = self._check_nans(context=context)
        if ans:
            return ans

        if self._isinfinity() == 1:
            return _Infinity
        if self._isinfinity() == -1:
            return _dec_from_triple(1, '9'*context.prec, context.Etop())

        context = context.copy()
        context._set_rounding(ROUND_CEILING)
        context._ignore_all_flags()
        new_self = self._fix(context)
        if new_self != self:
            return new_self
        return self.__add__(_dec_from_triple(0, '1', context.Etiny()-1),
                            context)

    def next_toward(self, other, context=None):
        """Returns the number closest to self, in the direction towards other.

        The result is the closest representable number to self
        (excluding self) that is in the direction towards other,
        unless both have the same value.  If the two operands are
        numerically equal, then the result is a copy of self with the
        sign set to be the same as the sign of other.
        """
        other = _convert_other(other, raiseit=True)

        if context is None:
            context = getcontext()

        ans = self._check_nans(other, context)
        if ans:
            return ans

        comparison = self._cmp(other)
        if comparison == 0:
            return self.copy_sign(other)

        if comparison == -1:
            ans = self.next_plus(context)
        else: # comparison == 1
            ans = self.next_minus(context)

        # decide which flags to raise using value of ans
        if ans._isinfinity():
            context._raise_error(Overflow,
                                 'Infinite result from next_toward',
                                 ans._sign)
            context._raise_error(Inexact)
            context._raise_error(Rounded)
        elif ans.adjusted() < context.Emin:
            context._raise_error(Underflow)
            context._raise_error(Subnormal)
            context._raise_error(Inexact)
            context._raise_error(Rounded)
            # if precision == 1 then we don't raise Clamped for a
            # result 0E-Etiny.
            if not ans:
                context._raise_error(Clamped)

        return ans

    def number_class(self, context=None):
        """Returns an indication of the class of self.

        The class is one of the following strings:
          sNaN
          NaN
          -Infinity
          -Normal
          -Subnormal
          -Zero
          +Zero
          +Subnormal
          +Normal
          +Infinity
        """
        if self.is_snan():
            return "sNaN"
        if self.is_qnan():
            return "NaN"
        inf = self._isinfinity()
        if inf == 1:
            return "+Infinity"
        if inf == -1:
            return "-Infinity"
        if self.is_zero():
            if self._sign:
                return "-Zero"
            else:
                return "+Zero"
        if context is None:
            context = getcontext()
        if self.is_subnormal(context=context):
            if self._sign:
                return "-Subnormal"
            else:
                return "+Subnormal"
        # just a normal, regular, boring number, :)
        if self._sign:
            return "-Normal"
        else:
            return "+Normal"

    def radix(self):
        """Just returns 10, as this is Decimal, :)"""
        return Decimal(10)

    def rotate(self, other, context=None):
        """Returns a rotated copy of self, value-of-other times."""
        if context is None:
            context = getcontext()

        other = _convert_other(other, raiseit=True)

        ans = self._check_nans(other, context)
        if ans:
            return ans

        if other._exp != 0:
            return context._raise_error(InvalidOperation)
        if not (-context.prec <= int(other) <= context.prec):
            return context._raise_error(InvalidOperation)

        if self._isinfinity():
            return Decimal(self)

        # get values, pad if necessary
        torot = int(other)
        rotdig = self._int
        topad = context.prec - len(rotdig)
        if topad > 0:
            rotdig = '0'*topad + rotdig
        elif topad < 0:
            rotdig = rotdig[-topad:]

        # let's rotate!
        rotated = rotdig[torot:] + rotdig[:torot]
        return _dec_from_triple(self._sign,
                                rotated.lstrip('0') or '0', self._exp)

    def scaleb(self, other, context=None):
        """Returns self operand after adding the second value to its exp."""
        if context is None:
            context = getcontext()

        other = _convert_other(other, raiseit=True)

        ans = self._check_nans(other, context)
        if ans:
            return ans

        if other._exp != 0:
            return context._raise_error(InvalidOperation)
        liminf = -2 * (context.Emax + context.prec)
        limsup =  2 * (context.Emax + context.prec)
        if not (liminf <= int(other) <= limsup):
            return context._raise_error(InvalidOperation)

        if self._isinfinity():
            return Decimal(self)

        d = _dec_from_triple(self._sign, self._int, self._exp + int(other))
        d = d._fix(context)
        return d

    def shift(self, other, context=None):
        """Returns a shifted copy of self, value-of-other times."""
        if context is None:
            context = getcontext()

        other = _convert_other(other, raiseit=True)

        ans = self._check_nans(other, context)
        if ans:
            return ans

        if other._exp != 0:
            return context._raise_error(InvalidOperation)
        if not (-context.prec <= int(other) <= context.prec):
            return context._raise_error(InvalidOperation)

        if self._isinfinity():
            return Decimal(self)

        # get values, pad if necessary
        torot = int(other)
        rotdig = self._int
        topad = context.prec - len(rotdig)
        if topad > 0:
            rotdig = '0'*topad + rotdig
        elif topad < 0:
            rotdig = rotdig[-topad:]

        # let's shift!
        if torot < 0:
            shifted = rotdig[:torot]
        else:
            shifted = rotdig + '0'*torot
            shifted = shifted[-context.prec:]

        return _dec_from_triple(self._sign,
                                    shifted.lstrip('0') or '0', self._exp)

    # Support for pickling, copy, and deepcopy
    def __reduce__(self):
        return (self.__class__, (str(self),))

    def __copy__(self):
        if type(self) is Decimal:
            return self     # I'm immutable; therefore I am my own clone
        return self.__class__(str(self))

    def __deepcopy__(self, memo):
        if type(self) is Decimal:
            return self     # My components are also immutable
        return self.__class__(str(self))

    # PEP 3101 support.  the _localeconv keyword argument should be
    # considered private: it's provided for ease of testing only.
    def __format__(self, specifier, context=None, _localeconv=None):
        """Format a Decimal instance according to the given specifier.

        The specifier should be a standard format specifier, with the
        form described in PEP 3101.  Formatting types 'e', 'E', 'f',
        'F', 'g', 'G', 'n' and '%' are supported.  If the formatting
        type is omitted it defaults to 'g' or 'G', depending on the
        value of context.capitals.
        """

        # Note: PEP 3101 says that if the type is not present then
        # there should be at least one digit after the decimal point.
        # We take the liberty of ignoring this requirement for
        # Decimal---it's presumably there to make sure that
        # format(float, '') behaves similarly to str(float).
        if context is None:
            context = getcontext()

        spec = _parse_format_specifier(specifier, _localeconv=_localeconv)

        # special values don't care about the type or precision
        if self._is_special:
            sign = _format_sign(self._sign, spec)
            body = str(self.copy_abs())
            if spec['type'] == '%':
                body += '%'
            return _format_align(sign, body, spec)

        # a type of None defaults to 'g' or 'G', depending on context
        if spec['type'] is None:
            spec['type'] = ['g', 'G'][context.capitals]

        # if type is '%', adjust exponent of self accordingly
        if spec['type'] == '%':
            self = _dec_from_triple(self._sign, self._int, self._exp+2)

        # round if necessary, taking rounding mode from the context
        rounding = context.rounding
        precision = spec['precision']
        if precision is not None:
            if spec['type'] in 'eE':
                self = self._round(precision+1, rounding)
            elif spec['type'] in 'fF%':
                self = self._rescale(-precision, rounding)
            elif spec['type'] in 'gG' and len(self._int) > precision:
                self = self._round(precision, rounding)
        # special case: zeros with a positive exponent can't be
        # represented in fixed point; rescale them to 0e0.
        if not self and self._exp > 0 and spec['type'] in 'fF%':
            self = self._rescale(0, rounding)
        if not self and spec['no_neg_0'] and self._sign:
            adjusted_sign = 0
        else:
            adjusted_sign = self._sign

        # figure out placement of the decimal point
        leftdigits = self._exp + len(self._int)
        if spec['type'] in 'eE':
            if not self and precision is not None:
                dotplace = 1 - precision
            else:
                dotplace = 1
        elif spec['type'] in 'fF%':
            dotplace = leftdigits
        elif spec['type'] in 'gG':
            if self._exp <= 0 and leftdigits > -6:
                dotplace = leftdigits
            else:
                dotplace = 1

        # find digits before and after decimal point, and get exponent
        if dotplace < 0:
            intpart = '0'
            fracpart = '0'*(-dotplace) + self._int
        elif dotplace > len(self._int):
            intpart = self._int + '0'*(dotplace-len(self._int))
            fracpart = ''
        else:
            intpart = self._int[:dotplace] or '0'
            fracpart = self._int[dotplace:]
        exp = leftdigits-dotplace

        # done with the decimal-specific stuff;  hand over the rest
        # of the formatting to the _format_number function
        return _format_number(adjusted_sign, intpart, fracpart, exp, spec)

def _dec_from_triple(sign, coefficient, exponent, special=False):
    """Create a decimal instance directly, without any validation,
    normalization (e.g. removal of leading zeros) or argument
    conversion.

    This function is for *internal use only*.
    """

    self = object.__new__(Decimal)
    self._sign = sign
    self._int = coefficient
    self._exp = exponent
    self._is_special = special

    return self

# Register Decimal as a kind of Number (an abstract base class).
# However, do not register it as Real (because Decimals are not
# interoperable with floats).
_numbers.Number.register(Decimal)


##### Context class #######################################################

class _ContextManager(object):
    """Context manager class to support localcontext().

      Sets a copy of the supplied context in __enter__() and restores
      the previous decimal context in __exit__()
    """
    def __init__(self, new_context):
        self.new_context = new_context.copy()
    def __enter__(self):
        self.saved_context = getcontext()
        setcontext(self.new_context)
        return self.new_context
    def __exit__(self, t, v, tb):
        setcontext(self.saved_context)

class Context(object):
    """Contains the context for a Decimal instance.

    Contains:
    prec - precision (for use in rounding, division, square roots..)
    rounding - rounding type (how you round)
    traps - If traps[exception] = 1, then the exception is
                    raised when it is caused.  Otherwise, a value is
                    substituted in.
    flags  - When an exception is caused, flags[exception] is set.
             (Whether or not the trap_enabler is set)
             Should be reset by user of Decimal instance.
    Emin -   Minimum exponent
    Emax -   Maximum exponent
    capitals -      If 1, 1*10^1 is printed as 1E+1.
                    If 0, printed as 1e1
    clamp -  If 1, change exponents if too high (Default 0)
    """

    def __init__(self, prec=None, rounding=None, Emin=None, Emax=None,
                       capitals=None, clamp=None, flags=None, traps=None,
                       _ignored_flags=None):
        # Set defaults; for everything except flags and _ignored_flags,
        # inherit from DefaultContext.
        try:
            dc = DefaultContext
        except NameError:
            pass

        self.prec = prec if prec is not None else dc.prec
        self.rounding = rounding if rounding is not None else dc.rounding
        self.Emin = Emin if Emin is not None else dc.Emin
        self.Emax = Emax if Emax is not None else dc.Emax
        self.capitals = capitals if capitals is not None else dc.capitals
        self.clamp = clamp if clamp is not None else dc.clamp

        if _ignored_flags is None:
            self._ignored_flags = []
        else:
            self._ignored_flags = _ignored_flags

        if traps is None:
            self.traps = dc.traps.copy()
        elif not isinstance(traps, dict):
            self.traps = dict((s, int(s in traps)) for s in _signals + traps)
        else:
            self.traps = traps

        if flags is None:
            self.flags = dict.fromkeys(_signals, 0)
        elif not isinstance(flags, dict):
            self.flags = dict((s, int(s in flags)) for s in _signals + flags)
        else:
            self.flags = flags

    def _set_integer_check(self, name, value, vmin, vmax):
        if not isinstance(value, int):
            raise TypeError("%s must be an integer" % name)
        if vmin == '-inf':
            if value > vmax:
                raise ValueError("%s must be in [%s, %d]. got: %s" % (name, vmin, vmax, value))
        elif vmax == 'inf':
            if value < vmin:
                raise ValueError("%s must be in [%d, %s]. got: %s" % (name, vmin, vmax, value))
        else:
            if value < vmin or value > vmax:
                raise ValueError("%s must be in [%d, %d]. got %s" % (name, vmin, vmax, value))
        return object.__setattr__(self, name, value)

    def _set_signal_dict(self, name, d):
        if not isinstance(d, dict):
            raise TypeError("%s must be a signal dict" % d)
        for key in d:
            if not key in _signals:
                raise KeyError("%s is not a valid signal dict" % d)
        for key in _signals:
            if not key in d:
                raise KeyError("%s is not a valid signal dict" % d)
        return object.__setattr__(self, name, d)

    def __setattr__(self, name, value):
        if name == 'prec':
            return self._set_integer_check(name, value, 1, 'inf')
        elif name == 'Emin':
            return self._set_integer_check(name, value, '-inf', 0)
        elif name == 'Emax':
            return self._set_integer_check(name, value, 0, 'inf')
        elif name == 'capitals':
            return self._set_integer_check(name, value, 0, 1)
        elif name == 'clamp':
            return self._set_integer_check(name, value, 0, 1)
        elif name == 'rounding':
            if not value in _rounding_modes:
                # raise TypeError even for strings to have consistency
                # among various implementations.
                raise TypeError("%s: invalid rounding mode" % value)
            return object.__setattr__(self, name, value)
        elif name == 'flags' or name == 'traps':
            return self._set_signal_dict(name, value)
        elif name == '_ignored_flags':
            return object.__setattr__(self, name, value)
        else:
            raise AttributeError(
                "'decimal.Context' object has no attribute '%s'" % name)

    def __delattr__(self, name):
        raise AttributeError("%s cannot be deleted" % name)

    # Support for pickling, copy, and deepcopy
    def __reduce__(self):
        flags = [sig for sig, v in self.flags.items() if v]
        traps = [sig for sig, v in self.traps.items() if v]
        return (self.__class__,
                (self.prec, self.rounding, self.Emin, self.Emax,
                 self.capitals, self.clamp, flags, traps))

    def __repr__(self):
        """Show the current context."""
        s = []
        s.append('Context(prec=%(prec)d, rounding=%(rounding)s, '
                 'Emin=%(Emin)d, Emax=%(Emax)d, capitals=%(capitals)d, '
                 'clamp=%(clamp)d'
                 % vars(self))
        names = [f.__name__ for f, v in self.flags.items() if v]
        s.append('flags=[' + ', '.join(names) + ']')
        names = [t.__name__ for t, v in self.traps.items() if v]
        s.append('traps=[' + ', '.join(names) + ']')
        return ', '.join(s) + ')'

    def clear_flags(self):
        """Reset all flags to zero"""
        for flag in self.flags:
            self.flags[flag] = 0

    def clear_traps(self):
        """Reset all traps to zero"""
        for flag in self.traps:
            self.traps[flag] = 0

    def _shallow_copy(self):
        """Returns a shallow copy from self."""
        nc = Context(self.prec, self.rounding, self.Emin, self.Emax,
                     self.capitals, self.clamp, self.flags, self.traps,
                     self._ignored_flags)
        return nc

    def copy(self):
        """Returns a deep copy from self."""
        nc = Context(self.prec, self.rounding, self.Emin, self.Emax,
                     self.capitals, self.clamp,
                     self.flags.copy(), self.traps.copy(),
                     self._ignored_flags)
        return nc
    __copy__ = copy

    def _raise_error(self, condition, explanation = None, *args):
        """Handles an error

        If the flag is in _ignored_flags, returns the default response.
        Otherwise, it sets the flag, then, if the corresponding
        trap_enabler is set, it reraises the exception.  Otherwise, it returns
        the default value after setting the flag.
        """
        error = _condition_map.get(condition, condition)
        if error in self._ignored_flags:
            # Don't touch the flag
            return error().handle(self, *args)

        self.flags[error] = 1
        if not self.traps[error]:
            # The errors define how to handle themselves.
            return condition().handle(self, *args)

        # Errors should only be risked on copies of the context
        # self._ignored_flags = []
        raise error(explanation)

    def _ignore_all_flags(self):
        """Ignore all flags, if they are raised"""
        return self._ignore_flags(*_signals)

    def _ignore_flags(self, *flags):
        """Ignore the flags, if they are raised"""
        # Do not mutate-- This way, copies of a context leave the original
        # alone.
        self._ignored_flags = (self._ignored_flags + list(flags))
        return list(flags)

    def _regard_flags(self, *flags):
        """Stop ignoring the flags, if they are raised"""
        if flags and isinstance(flags[0], (tuple,list)):
            flags = flags[0]
        for flag in flags:
            self._ignored_flags.remove(flag)

    # We inherit object.__hash__, so we must deny this explicitly
    __hash__ = None

    def Etiny(self):
        """Returns Etiny (= Emin - prec + 1)"""
        return int(self.Emin - self.prec + 1)

    def Etop(self):
        """Returns maximum exponent (= Emax - prec + 1)"""
        return int(self.Emax - self.prec + 1)

    def _set_rounding(self, type):
        """Sets the rounding type.

        Sets the rounding type, and returns the current (previous)
        rounding type.  Often used like:

        context = context.copy()
        # so you don't change the calling context
        # if an error occurs in the middle.
        rounding = context._set_rounding(ROUND_UP)
        val = self.__sub__(other, context=context)
        context._set_rounding(rounding)

        This will make it round up for that operation.
        """
        rounding = self.rounding
        self.rounding = type
        return rounding

    def create_decimal(self, num='0'):
        """Creates a new Decimal instance but using self as context.

        This method implements the to-number operation of the
        IBM Decimal specification."""

        if isinstance(num, str) and (num != num.strip() or '_' in num):
            return self._raise_error(ConversionSyntax,
                                     "trailing or leading whitespace and "
                                     "underscores are not permitted.")

        d = Decimal(num, context=self)
        if d._isnan() and len(d._int) > self.prec - self.clamp:
            return self._raise_error(ConversionSyntax,
                                     "diagnostic info too long in NaN")
        return d._fix(self)

    def create_decimal_from_float(self, f):
        """Creates a new Decimal instance from a float but rounding using self
        as the context.

        >>> context = Context(prec=5, rounding=ROUND_DOWN)
        >>> context.create_decimal_from_float(3.1415926535897932)
        Decimal('3.1415')
        >>> context = Context(prec=5, traps=[Inexact])
        >>> context.create_decimal_from_float(3.1415926535897932)
        Traceback (most recent call last):
            ...
        decimal.Inexact: None

        """
        d = Decimal.from_float(f)       # An exact conversion
        return d._fix(self)             # Apply the context rounding

    # Methods
    def abs(self, a):
        """Returns the absolute value of the operand.

        If the operand is negative, the result is the same as using the minus
        operation on the operand.  Otherwise, the result is the same as using
        the plus operation on the operand.

        >>> ExtendedContext.abs(Decimal('2.1'))
        Decimal('2.1')
        >>> ExtendedContext.abs(Decimal('-100'))
        Decimal('100')
        >>> ExtendedContext.abs(Decimal('101.5'))
        Decimal('101.5')
        >>> ExtendedContext.abs(Decimal('-101.5'))
        Decimal('101.5')
        >>> ExtendedContext.abs(-1)
        Decimal('1')
        """
        a = _convert_other(a, raiseit=True)
        return a.__abs__(context=self)

    def add(self, a, b):
        """Return the sum of the two operands.

        >>> ExtendedContext.add(Decimal('12'), Decimal('7.00'))
        Decimal('19.00')
        >>> ExtendedContext.add(Decimal('1E+2'), Decimal('1.01E+4'))
        Decimal('1.02E+4')
        >>> ExtendedContext.add(1, Decimal(2))
        Decimal('3')
        >>> ExtendedContext.add(Decimal(8), 5)
        Decimal('13')
        >>> ExtendedContext.add(5, 5)
        Decimal('10')
        """
        a = _convert_other(a, raiseit=True)
        r = a.__add__(b, context=self)
        if r is NotImplemented:
            raise TypeError("Unable to convert %s to Decimal" % b)
        else:
            return r

    def _apply(self, a):
        return str(a._fix(self))

    def canonical(self, a):
        """Returns the same Decimal object.

        As we do not have different encodings for the same number, the
        received object already is in its canonical form.

        >>> ExtendedContext.canonical(Decimal('2.50'))
        Decimal('2.50')
        """
        if not isinstance(a, Decimal):
            raise TypeError("canonical requires a Decimal as an argument.")
        return a.canonical()

    def compare(self, a, b):
        """Compares values numerically.

        If the signs of the operands differ, a value representing each operand
        ('-1' if the operand is less than zero, '0' if the operand is zero or
        negative zero, or '1' if the operand is greater than zero) is used in
        place of that operand for the comparison instead of the actual
        operand.

        The comparison is then effected by subtracting the second operand from
        the first and then returning a value according to the result of the
        subtraction: '-1' if the result is less than zero, '0' if the result is
        zero or negative zero, or '1' if the result is greater than zero.

        >>> ExtendedContext.compare(Decimal('2.1'), Decimal('3'))
        Decimal('-1')
        >>> ExtendedContext.compare(Decimal('2.1'), Decimal('2.1'))
        Decimal('0')
        >>> ExtendedContext.compare(Decimal('2.1'), Decimal('2.10'))
        Decimal('0')
        >>> ExtendedContext.compare(Decimal('3'), Decimal('2.1'))
        Decimal('1')
        >>> ExtendedContext.compare(Decimal('2.1'), Decimal('-3'))
        Decimal('1')
        >>> ExtendedContext.compare(Decimal('-3'), Decimal('2.1'))
        Decimal('-1')
        >>> ExtendedContext.compare(1, 2)
        Decimal('-1')
        >>> ExtendedContext.compare(Decimal(1), 2)
        Decimal('-1')
        >>> ExtendedContext.compare(1, Decimal(2))
        Decimal('-1')
        """
        a = _convert_other(a, raiseit=True)
        return a.compare(b, context=self)

    def compare_signal(self, a, b):
        """Compares the values of the two operands numerically.

        It's pretty much like compare(), but all NaNs signal, with signaling
        NaNs taking precedence over quiet NaNs.

        >>> c = ExtendedContext
        >>> c.compare_signal(Decimal('2.1'), Decimal('3'))
        Decimal('-1')
        >>> c.compare_signal(Decimal('2.1'), Decimal('2.1'))
        Decimal('0')
        >>> c.flags[InvalidOperation] = 0
        >>> print(c.flags[InvalidOperation])
        0
        >>> c.compare_signal(Decimal('NaN'), Decimal('2.1'))
        Decimal('NaN')
        >>> print(c.flags[InvalidOperation])
        1
        >>> c.flags[InvalidOperation] = 0
        >>> print(c.flags[InvalidOperation])
        0
        >>> c.compare_signal(Decimal('sNaN'), Decimal('2.1'))
        Decimal('NaN')
        >>> print(c.flags[InvalidOperation])
        1
        >>> c.compare_signal(-1, 2)
        Decimal('-1')
        >>> c.compare_signal(Decimal(-1), 2)
        Decimal('-1')
        >>> c.compare_signal(-1, Decimal(2))
        Decimal('-1')
        """
        a = _convert_other(a, raiseit=True)
        return a.compare_signal(b, context=self)

    def compare_total(self, a, b):
        """Compares two operands using their abstract representation.

        This is not like the standard compare, which use their numerical
        value. Note that a total ordering is defined for all possible abstract
        representations.

        >>> ExtendedContext.compare_total(Decimal('12.73'), Decimal('127.9'))
        Decimal('-1')
        >>> ExtendedContext.compare_total(Decimal('-127'),  Decimal('12'))
        Decimal('-1')
        >>> ExtendedContext.compare_total(Decimal('12.30'), Decimal('12.3'))
        Decimal('-1')
        >>> ExtendedContext.compare_total(Decimal('12.30'), Decimal('12.30'))
        Decimal('0')
        >>> ExtendedContext.compare_total(Decimal('12.3'),  Decimal('12.300'))
        Decimal('1')
        >>> ExtendedContext.compare_total(Decimal('12.3'),  Decimal('NaN'))
        Decimal('-1')
        >>> ExtendedContext.compare_total(1, 2)
        Decimal('-1')
        >>> ExtendedContext.compare_total(Decimal(1), 2)
        Decimal('-1')
        >>> ExtendedContext.compare_total(1, Decimal(2))
        Decimal('-1')
        """
        a = _convert_other(a, raiseit=True)
        return a.compare_total(b)

    def compare_total_mag(self, a, b):
        """Compares two operands using their abstract representation ignoring sign.

        Like compare_total, but with operand's sign ignored and assumed to be 0.
        """
        a = _convert_other(a, raiseit=True)
        return a.compare_total_mag(b)

    def copy_abs(self, a):
        """Returns a copy of the operand with the sign set to 0.

        >>> ExtendedContext.copy_abs(Decimal('2.1'))
        Decimal('2.1')
        >>> ExtendedContext.copy_abs(Decimal('-100'))
        Decimal('100')
        >>> ExtendedContext.copy_abs(-1)
        Decimal('1')
        """
        a = _convert_other(a, raiseit=True)
        return a.copy_abs()

    def copy_decimal(self, a):
        """Returns a copy of the decimal object.

        >>> ExtendedContext.copy_decimal(Decimal('2.1'))
        Decimal('2.1')
        >>> ExtendedContext.copy_decimal(Decimal('-1.00'))
        Decimal('-1.00')
        >>> ExtendedContext.copy_decimal(1)
        Decimal('1')
        """
        a = _convert_other(a, raiseit=True)
        return Decimal(a)

    def copy_negate(self, a):
        """Returns a copy of the operand with the sign inverted.

        >>> ExtendedContext.copy_negate(Decimal('101.5'))
        Decimal('-101.5')
        >>> ExtendedContext.copy_negate(Decimal('-101.5'))
        Decimal('101.5')
        >>> ExtendedContext.copy_negate(1)
        Decimal('-1')
        """
        a = _convert_other(a, raiseit=True)
        return a.copy_negate()

    def copy_sign(self, a, b):
        """Copies the second operand's sign to the first one.

        In detail, it returns a copy of the first operand with the sign
        equal to the sign of the second operand.

        >>> ExtendedContext.copy_sign(Decimal( '1.50'), Decimal('7.33'))
        Decimal('1.50')
        >>> ExtendedContext.copy_sign(Decimal('-1.50'), Decimal('7.33'))
        Decimal('1.50')
        >>> ExtendedContext.copy_sign(Decimal( '1.50'), Decimal('-7.33'))
        Decimal('-1.50')
        >>> ExtendedContext.copy_sign(Decimal('-1.50'), Decimal('-7.33'))
        Decimal('-1.50')
        >>> ExtendedContext.copy_sign(1, -2)
        Decimal('-1')
        >>> ExtendedContext.copy_sign(Decimal(1), -2)
        Decimal('-1')
        >>> ExtendedContext.copy_sign(1, Decimal(-2))
        Decimal('-1')
        """
        a = _convert_other(a, raiseit=True)
        return a.copy_sign(b)

    def divide(self, a, b):
        """Decimal division in a specified context.

        >>> ExtendedContext.divide(Decimal('1'), Decimal('3'))
        Decimal('0.333333333')
        >>> ExtendedContext.divide(Decimal('2'), Decimal('3'))
        Decimal('0.666666667')
        >>> ExtendedContext.divide(Decimal('5'), Decimal('2'))
        Decimal('2.5')
        >>> ExtendedContext.divide(Decimal('1'), Decimal('10'))
        Decimal('0.1')
        >>> ExtendedContext.divide(Decimal('12'), Decimal('12'))
        Decimal('1')
        >>> ExtendedContext.divide(Decimal('8.00'), Decimal('2'))
        Decimal('4.00')
        >>> ExtendedContext.divide(Decimal('2.400'), Decimal('2.0'))
        Decimal('1.20')
        >>> ExtendedContext.divide(Decimal('1000'), Decimal('100'))
        Decimal('10')
        >>> ExtendedContext.divide(Decimal('1000'), Decimal('1'))
        Decimal('1000')
        >>> ExtendedContext.divide(Decimal('2.40E+6'), Decimal('2'))
        Decimal('1.20E+6')
        >>> ExtendedContext.divide(5, 5)
        Decimal('1')
        >>> ExtendedContext.divide(Decimal(5), 5)
        Decimal('1')
        >>> ExtendedContext.divide(5, Decimal(5))
        Decimal('1')
        """
        a = _convert_other(a, raiseit=True)
        r = a.__truediv__(b, context=self)
        if r is NotImplemented:
            raise TypeError("Unable to convert %s to Decimal" % b)
        else:
            return r

    def divide_int(self, a, b):
        """Divides two numbers and returns the integer part of the result.

        >>> ExtendedContext.divide_int(Decimal('2'), Decimal('3'))
        Decimal('0')
        >>> ExtendedContext.divide_int(Decimal('10'), Decimal('3'))
        Decimal('3')
        >>> ExtendedContext.divide_int(Decimal('1'), Decimal('0.3'))
        Decimal('3')
        >>> ExtendedContext.divide_int(10, 3)
        Decimal('3')
        >>> ExtendedContext.divide_int(Decimal(10), 3)
        Decimal('3')
        >>> ExtendedContext.divide_int(10, Decimal(3))
        Decimal('3')
        """
        a = _convert_other(a, raiseit=True)
        r = a.__floordiv__(b, context=self)
        if r is NotImplemented:
            raise TypeError("Unable to convert %s to Decimal" % b)
        else:
            return r

    def divmod(self, a, b):
        """Return (a // b, a % b).

        >>> ExtendedContext.divmod(Decimal(8), Decimal(3))
        (Decimal('2'), Decimal('2'))
        >>> ExtendedContext.divmod(Decimal(8), Decimal(4))
        (Decimal('2'), Decimal('0'))
        >>> ExtendedContext.divmod(8, 4)
        (Decimal('2'), Decimal('0'))
        >>> ExtendedContext.divmod(Decimal(8), 4)
        (Decimal('2'), Decimal('0'))
        >>> ExtendedContext.divmod(8, Decimal(4))
        (Decimal('2'), Decimal('0'))
        """
        a = _convert_other(a, raiseit=True)
        r = a.__divmod__(b, context=self)
        if r is NotImplemented:
            raise TypeError("Unable to convert %s to Decimal" % b)
        else:
            return r

    def exp(self, a):
        """Returns e ** a.

        >>> c = ExtendedContext.copy()
        >>> c.Emin = -999
        >>> c.Emax = 999
        >>> c.exp(Decimal('-Infinity'))
        Decimal('0')
        >>> c.exp(Decimal('-1'))
        Decimal('0.367879441')
        >>> c.exp(Decimal('0'))
        Decimal('1')
        >>> c.exp(Decimal('1'))
        Decimal('2.71828183')
        >>> c.exp(Decimal('0.693147181'))
        Decimal('2.00000000')
        >>> c.exp(Decimal('+Infinity'))
        Decimal('Infinity')
        >>> c.exp(10)
        Decimal('22026.4658')
        """
        a =_convert_other(a, raiseit=True)
        return a.exp(context=self)

    def fma(self, a, b, c):
        """Returns a multiplied by b, plus c.

        The first two operands are multiplied together, using multiply,
        the third operand is then added to the result of that
        multiplication, using add, all with only one final rounding.

        >>> ExtendedContext.fma(Decimal('3'), Decimal('5'), Decimal('7'))
        Decimal('22')
        >>> ExtendedContext.fma(Decimal('3'), Decimal('-5'), Decimal('7'))
        Decimal('-8')
        >>> ExtendedContext.fma(Decimal('888565290'), Decimal('1557.96930'), Decimal('-86087.7578'))
        Decimal('1.38435736E+12')
        >>> ExtendedContext.fma(1, 3, 4)
        Decimal('7')
        >>> ExtendedContext.fma(1, Decimal(3), 4)
        Decimal('7')
        >>> ExtendedContext.fma(1, 3, Decimal(4))
        Decimal('7')
        """
        a = _convert_other(a, raiseit=True)
        return a.fma(b, c, context=self)

    def is_canonical(self, a):
        """Return True if the operand is canonical; otherwise return False.

        Currently, the encoding of a Decimal instance is always
        canonical, so this method returns True for any Decimal.

        >>> ExtendedContext.is_canonical(Decimal('2.50'))
        True
        """
        if not isinstance(a, Decimal):
            raise TypeError("is_canonical requires a Decimal as an argument.")
        return a.is_canonical()

    def is_finite(self, a):
        """Return True if the operand is finite; otherwise return False.

        A Decimal instance is considered finite if it is neither
        infinite nor a NaN.

        >>> ExtendedContext.is_finite(Decimal('2.50'))
        True
        >>> ExtendedContext.is_finite(Decimal('-0.3'))
        True
        >>> ExtendedContext.is_finite(Decimal('0'))
        True
        >>> ExtendedContext.is_finite(Decimal('Inf'))
        False
        >>> ExtendedContext.is_finite(Decimal('NaN'))
        False
        >>> ExtendedContext.is_finite(1)
        True
        """
        a = _convert_other(a, raiseit=True)
        return a.is_finite()

    def is_infinite(self, a):
        """Return True if the operand is infinite; otherwise return False.

        >>> ExtendedContext.is_infinite(Decimal('2.50'))
        False
        >>> ExtendedContext.is_infinite(Decimal('-Inf'))
        True
        >>> ExtendedContext.is_infinite(Decimal('NaN'))
        False
        >>> ExtendedContext.is_infinite(1)
        False
        """
        a = _convert_other(a, raiseit=True)
        return a.is_infinite()

    def is_nan(self, a):
        """Return True if the operand is a qNaN or sNaN;
        otherwise return False.

        >>> ExtendedContext.is_nan(Decimal('2.50'))
        False
        >>> ExtendedContext.is_nan(Decimal('NaN'))
        True
        >>> ExtendedContext.is_nan(Decimal('-sNaN'))
        True
        >>> ExtendedContext.is_nan(1)
        False
        """
        a = _convert_other(a, raiseit=True)
        return a.is_nan()

    def is_normal(self, a):
        """Return True if the operand is a normal number;
        otherwise return False.

        >>> c = ExtendedContext.copy()
        >>> c.Emin = -999
        >>> c.Emax = 999
        >>> c.is_normal(Decimal('2.50'))
        True
        >>> c.is_normal(Decimal('0.1E-999'))
        False
        >>> c.is_normal(Decimal('0.00'))
        False
        >>> c.is_normal(Decimal('-Inf'))
        False
        >>> c.is_normal(Decimal('NaN'))
        False
        >>> c.is_normal(1)
        True
        """
        a = _convert_other(a, raiseit=True)
        return a.is_normal(context=self)

    def is_qnan(self, a):
        """Return True if the operand is a quiet NaN; otherwise return False.

        >>> ExtendedContext.is_qnan(Decimal('2.50'))
        False
        >>> ExtendedContext.is_qnan(Decimal('NaN'))
        True
        >>> ExtendedContext.is_qnan(Decimal('sNaN'))
        False
        >>> ExtendedContext.is_qnan(1)
        False
        """
        a = _convert_other(a, raiseit=True)
        return a.is_qnan()

    def is_signed(self, a):
        """Return True if the operand is negative; otherwise return False.

        >>> ExtendedContext.is_signed(Decimal('2.50'))
        False
        >>> ExtendedContext.is_signed(Decimal('-12'))
        True
        >>> ExtendedContext.is_signed(Decimal('-0'))
        True
        >>> ExtendedContext.is_signed(8)
        False
        >>> ExtendedContext.is_signed(-8)
        True
        """
        a = _convert_other(a, raiseit=True)
        return a.is_signed()

    def is_snan(self, a):
        """Return True if the operand is a signaling NaN;
        otherwise return False.

        >>> ExtendedContext.is_snan(Decimal('2.50'))
        False
        >>> ExtendedContext.is_snan(Decimal('NaN'))
        False
        >>> ExtendedContext.is_snan(Decimal('sNaN'))
        True
        >>> ExtendedContext.is_snan(1)
        False
        """
        a = _convert_other(a, raiseit=True)
        return a.is_snan()

    def is_subnormal(self, a):
        """Return True if the operand is subnormal; otherwise return False.

        >>> c = ExtendedContext.copy()
        >>> c.Emin = -999
        >>> c.Emax = 999
        >>> c.is_subnormal(Decimal('2.50'))
        False
        >>> c.is_subnormal(Decimal('0.1E-999'))
        True
        >>> c.is_subnormal(Decimal('0.00'))
        False
        >>> c.is_subnormal(Decimal('-Inf'))
        False
        >>> c.is_subnormal(Decimal('NaN'))
        False
        >>> c.is_subnormal(1)
        False
        """
        a = _convert_other(a, raiseit=True)
        return a.is_subnormal(context=self)

    def is_zero(self, a):
        """Return True if the operand is a zero; otherwise return False.

        >>> ExtendedContext.is_zero(Decimal('0'))
        True
        >>> ExtendedContext.is_zero(Decimal('2.50'))
        False
        >>> ExtendedContext.is_zero(Decimal('-0E+2'))
        True
        >>> ExtendedContext.is_zero(1)
        False
        >>> ExtendedContext.is_zero(0)
        True
        """
        a = _convert_other(a, raiseit=True)
        return a.is_zero()

    def ln(self, a):
        """Returns the natural (base e) logarithm of the operand.

        >>> c = ExtendedContext.copy()
        >>> c.Emin = -999
        >>> c.Emax = 999
        >>> c.ln(Decimal('0'))
        Decimal('-Infinity')
        >>> c.ln(Decimal('1.000'))
        Decimal('0')
        >>> c.ln(Decimal('2.71828183'))
        Decimal('1.00000000')
        >>> c.ln(Decimal('10'))
        Decimal('2.30258509')
        >>> c.ln(Decimal('+Infinity'))
        Decimal('Infinity')
        >>> c.ln(1)
        Decimal('0')
        """
        a = _convert_other(a, raiseit=True)
        return a.ln(context=self)

    def log10(self, a):
        """Returns the base 10 logarithm of the operand.

        >>> c = ExtendedContext.copy()
        >>> c.Emin = -999
        >>> c.Emax = 999
        >>> c.log10(Decimal('0'))
        Decimal('-Infinity')
        >>> c.log10(Decimal('0.001'))
        Decimal('-3')
        >>> c.log10(Decimal('1.000'))
        Decimal('0')
        >>> c.log10(Decimal('2'))
        Decimal('0.301029996')
        >>> c.log10(Decimal('10'))
        Decimal('1')
        >>> c.log10(Decimal('70'))
        Decimal('1.84509804')
        >>> c.log10(Decimal('+Infinity'))
        Decimal('Infinity')
        >>> c.log10(0)
        Decimal('-Infinity')
        >>> c.log10(1)
        Decimal('0')
        """
        a = _convert_other(a, raiseit=True)
        return a.log10(context=self)

    def logb(self, a):
        """ Returns the exponent of the magnitude of the operand's MSD.

        The result is the integer which is the exponent of the magnitude
        of the most significant digit of the operand (as though the
        operand were truncated to a single digit while maintaining the
        value of that digit and without limiting the resulting exponent).

        >>> ExtendedContext.logb(Decimal('250'))
        Decimal('2')
        >>> ExtendedContext.logb(Decimal('2.50'))
        Decimal('0')
        >>> ExtendedContext.logb(Decimal('0.03'))
        Decimal('-2')
        >>> ExtendedContext.logb(Decimal('0'))
        Decimal('-Infinity')
        >>> ExtendedContext.logb(1)
        Decimal('0')
        >>> ExtendedContext.logb(10)
        Decimal('1')
        >>> ExtendedContext.logb(100)
        Decimal('2')
        """
        a = _convert_other(a, raiseit=True)
        return a.logb(context=self)

    def logical_and(self, a, b):
        """Applies the logical operation 'and' between each operand's digits.

        The operands must be both logical numbers.

        >>> ExtendedContext.logical_and(Decimal('0'), Decimal('0'))
        Decimal('0')
        >>> ExtendedContext.logical_and(Decimal('0'), Decimal('1'))
        Decimal('0')
        >>> ExtendedContext.logical_and(Decimal('1'), Decimal('0'))
        Decimal('0')
        >>> ExtendedContext.logical_and(Decimal('1'), Decimal('1'))
        Decimal('1')
        >>> ExtendedContext.logical_and(Decimal('1100'), Decimal('1010'))
        Decimal('1000')
        >>> ExtendedContext.logical_and(Decimal('1111'), Decimal('10'))
        Decimal('10')
        >>> ExtendedContext.logical_and(110, 1101)
        Decimal('100')
        >>> ExtendedContext.logical_and(Decimal(110), 1101)
        Decimal('100')
        >>> ExtendedContext.logical_and(110, Decimal(1101))
        Decimal('100')
        """
        a = _convert_other(a, raiseit=True)
        return a.logical_and(b, context=self)

    def logical_invert(self, a):
        """Invert all the digits in the operand.

        The operand must be a logical number.

        >>> ExtendedContext.logical_invert(Decimal('0'))
        Decimal('111111111')
        >>> ExtendedContext.logical_invert(Decimal('1'))
        Decimal('111111110')
        >>> ExtendedContext.logical_invert(Decimal('111111111'))
        Decimal('0')
        >>> ExtendedContext.logical_invert(Decimal('101010101'))
        Decimal('10101010')
        >>> ExtendedContext.logical_invert(1101)
        Decimal('111110010')
        """
        a = _convert_other(a, raiseit=True)
        return a.logical_invert(context=self)

    def logical_or(self, a, b):
        """Applies the logical operation 'or' between each operand's digits.

        The operands must be both logical numbers.

        >>> ExtendedContext.logical_or(Decimal('0'), Decimal('0'))
        Decimal('0')
        >>> ExtendedContext.logical_or(Decimal('0'), Decimal('1'))
        Decimal('1')
        >>> ExtendedContext.logical_or(Decimal('1'), Decimal('0'))
        Decimal('1')
        >>> ExtendedContext.logical_or(Decimal('1'), Decimal('1'))
        Decimal('1')
        >>> ExtendedContext.logical_or(Decimal('1100'), Decimal('1010'))
        Decimal('1110')
        >>> ExtendedContext.logical_or(Decimal('1110'), Decimal('10'))
        Decimal('1110')
        >>> ExtendedContext.logical_or(110, 1101)
        Decimal('1111')
        >>> ExtendedContext.logical_or(Decimal(110), 1101)
        Decimal('1111')
        >>> ExtendedContext.logical_or(110, Decimal(1101))
        Decimal('1111')
        """
        a = _convert_other(a, raiseit=True)
        return a.logical_or(b, context=self)

    def logical_xor(self, a, b):
        """Applies the logical operation 'xor' between each operand's digits.

        The operands must be both logical numbers.

        >>> ExtendedContext.logical_xor(Decimal('0'), Decimal('0'))
        Decimal('0')
        >>> ExtendedContext.logical_xor(Decimal('0'), Decimal('1'))
        Decimal('1')
        >>> ExtendedContext.logical_xor(Decimal('1'), Decimal('0'))
        Decimal('1')
        >>> ExtendedContext.logical_xor(Decimal('1'), Decimal('1'))
        Decimal('0')
        >>> ExtendedContext.logical_xor(Decimal('1100'), Decimal('1010'))
        Decimal('110')
        >>> ExtendedContext.logical_xor(Decimal('1111'), Decimal('10'))
        Decimal('1101')
        >>> ExtendedContext.logical_xor(110, 1101)
        Decimal('1011')
        >>> ExtendedContext.logical_xor(Decimal(110), 1101)
        Decimal('1011')
        >>> ExtendedContext.logical_xor(110, Decimal(1101))
        Decimal('1011')
        """
        a = _convert_other(a, raiseit=True)
        return a.logical_xor(b, context=self)

    def max(self, a, b):
        """max compares two values numerically and returns the maximum.

        If either operand is a NaN then the general rules apply.
        Otherwise, the operands are compared as though by the compare
        operation.  If they are numerically equal then the left-hand operand
        is chosen as the result.  Otherwise the maximum (closer to positive
        infinity) of the two operands is chosen as the result.

        >>> ExtendedContext.max(Decimal('3'), Decimal('2'))
        Decimal('3')
        >>> ExtendedContext.max(Decimal('-10'), Decimal('3'))
        Decimal('3')
        >>> ExtendedContext.max(Decimal('1.0'), Decimal('1'))
        Decimal('1')
        >>> ExtendedContext.max(Decimal('7'), Decimal('NaN'))
        Decimal('7')
        >>> ExtendedContext.max(1, 2)
        Decimal('2')
        >>> ExtendedContext.max(Decimal(1), 2)
        Decimal('2')
        >>> ExtendedContext.max(1, Decimal(2))
        Decimal('2')
        """
        a = _convert_other(a, raiseit=True)
        return a.max(b, context=self)

    def max_mag(self, a, b):
        """Compares the values numerically with their sign ignored.

        >>> ExtendedContext.max_mag(Decimal('7'), Decimal('NaN'))
        Decimal('7')
        >>> ExtendedContext.max_mag(Decimal('7'), Decimal('-10'))
        Decimal('-10')
        >>> ExtendedContext.max_mag(1, -2)
        Decimal('-2')
        >>> ExtendedContext.max_mag(Decimal(1), -2)
        Decimal('-2')
        >>> ExtendedContext.max_mag(1, Decimal(-2))
        Decimal('-2')
        """
        a = _convert_other(a, raiseit=True)
        return a.max_mag(b, context=self)

    def min(self, a, b):
        """min compares two values numerically and returns the minimum.

        If either operand is a NaN then the general rules apply.
        Otherwise, the operands are compared as though by the compare
        operation.  If they are numerically equal then the left-hand operand
        is chosen as the result.  Otherwise the minimum (closer to negative
        infinity) of the two operands is chosen as the result.

        >>> ExtendedContext.min(Decimal('3'), Decimal('2'))
        Decimal('2')
        >>> ExtendedContext.min(Decimal('-10'), Decimal('3'))
        Decimal('-10')
        >>> ExtendedContext.min(Decimal('1.0'), Decimal('1'))
        Decimal('1.0')
        >>> ExtendedContext.min(Decimal('7'), Decimal('NaN'))
        Decimal('7')
        >>> ExtendedContext.min(1, 2)
        Decimal('1')
        >>> ExtendedContext.min(Decimal(1), 2)
        Decimal('1')
        >>> ExtendedContext.min(1, Decimal(29))
        Decimal('1')
        """
        a = _convert_other(a, raiseit=True)
        return a.min(b, context=self)

    def min_mag(self, a, b):
        """Compares the values numerically with their sign ignored.

        >>> ExtendedContext.min_mag(Decimal('3'), Decimal('-2'))
        Decimal('-2')
        >>> ExtendedContext.min_mag(Decimal('-3'), Decimal('NaN'))
        Decimal('-3')
        >>> ExtendedContext.min_mag(1, -2)
        Decimal('1')
        >>> ExtendedContext.min_mag(Decimal(1), -2)
        Decimal('1')
        >>> ExtendedContext.min_mag(1, Decimal(-2))
        Decimal('1')
        """
        a = _convert_other(a, raiseit=True)
        return a.min_mag(b, context=self)

    def minus(self, a):
        """Minus corresponds to unary prefix minus in Python.

        The operation is evaluated using the same rules as subtract; the
        operation minus(a) is calculated as subtract('0', a) where the '0'
        has the same exponent as the operand.

        >>> ExtendedContext.minus(Decimal('1.3'))
        Decimal('-1.3')
        >>> ExtendedContext.minus(Decimal('-1.3'))
        Decimal('1.3')
        >>> ExtendedContext.minus(1)
        Decimal('-1')
        """
        a = _convert_other(a, raiseit=True)
        return a.__neg__(context=self)

    def multiply(self, a, b):
        """multiply multiplies two operands.

        If either operand is a special value then the general rules apply.
        Otherwise, the operands are multiplied together
        ('long multiplication'), resulting in a number which may be as long as
        the sum of the lengths of the two operands.

        >>> ExtendedContext.multiply(Decimal('1.20'), Decimal('3'))
        Decimal('3.60')
        >>> ExtendedContext.multiply(Decimal('7'), Decimal('3'))
        Decimal('21')
        >>> ExtendedContext.multiply(Decimal('0.9'), Decimal('0.8'))
        Decimal('0.72')
        >>> ExtendedContext.multiply(Decimal('0.9'), Decimal('-0'))
        Decimal('-0.0')
        >>> ExtendedContext.multiply(Decimal('654321'), Decimal('654321'))
        Decimal('4.28135971E+11')
        >>> ExtendedContext.multiply(7, 7)
        Decimal('49')
        >>> ExtendedContext.multiply(Decimal(7), 7)
        Decimal('49')
        >>> ExtendedContext.multiply(7, Decimal(7))
        Decimal('49')
        """
        a = _convert_other(a, raiseit=True)
        r = a.__mul__(b, context=self)
        if r is NotImplemented:
            raise TypeError("Unable to convert %s to Decimal" % b)
        else:
            return r

    def next_minus(self, a):
        """Returns the largest representable number smaller than a.

        >>> c = ExtendedContext.copy()
        >>> c.Emin = -999
        >>> c.Emax = 999
        >>> ExtendedContext.next_minus(Decimal('1'))
        Decimal('0.999999999')
        >>> c.next_minus(Decimal('1E-1007'))
        Decimal('0E-1007')
        >>> ExtendedContext.next_minus(Decimal('-1.00000003'))
        Decimal('-1.00000004')
        >>> c.next_minus(Decimal('Infinity'))
        Decimal('9.99999999E+999')
        >>> c.next_minus(1)
        Decimal('0.999999999')
        """
        a = _convert_other(a, raiseit=True)
        return a.next_minus(context=self)

    def next_plus(self, a):
        """Returns the smallest representable number larger than a.

        >>> c = ExtendedContext.copy()
        >>> c.Emin = -999
        >>> c.Emax = 999
        >>> ExtendedContext.next_plus(Decimal('1'))
        Decimal('1.00000001')
        >>> c.next_plus(Decimal('-1E-1007'))
        Decimal('-0E-1007')
        >>> ExtendedContext.next_plus(Decimal('-1.00000003'))
        Decimal('-1.00000002')
        >>> c.next_plus(Decimal('-Infinity'))
        Decimal('-9.99999999E+999')
        >>> c.next_plus(1)
        Decimal('1.00000001')
        """
        a = _convert_other(a, raiseit=True)
        return a.next_plus(context=self)

    def next_toward(self, a, b):
        """Returns the number closest to a, in direction towards b.

        The result is the closest representable number from the first
        operand (but not the first operand) that is in the direction
        towards the second operand, unless the operands have the same
        value.

        >>> c = ExtendedContext.copy()
        >>> c.Emin = -999
        >>> c.Emax = 999
        >>> c.next_toward(Decimal('1'), Decimal('2'))
        Decimal('1.00000001')
        >>> c.next_toward(Decimal('-1E-1007'), Decimal('1'))
        Decimal('-0E-1007')
        >>> c.next_toward(Decimal('-1.00000003'), Decimal('0'))
        Decimal('-1.00000002')
        >>> c.next_toward(Decimal('1'), Decimal('0'))
        Decimal('0.999999999')
        >>> c.next_toward(Decimal('1E-1007'), Decimal('-100'))
        Decimal('0E-1007')
        >>> c.next_toward(Decimal('-1.00000003'), Decimal('-10'))
        Decimal('-1.00000004')
        >>> c.next_toward(Decimal('0.00'), Decimal('-0.0000'))
        Decimal('-0.00')
        >>> c.next_toward(0, 1)
        Decimal('1E-1007')
        >>> c.next_toward(Decimal(0), 1)
        Decimal('1E-1007')
        >>> c.next_toward(0, Decimal(1))
        Decimal('1E-1007')
        """
        a = _convert_other(a, raiseit=True)
        return a.next_toward(b, context=self)

    def normalize(self, a):
        """normalize reduces an operand to its simplest form.

        Essentially a plus operation with all trailing zeros removed from the
        result.

        >>> ExtendedContext.normalize(Decimal('2.1'))
        Decimal('2.1')
        >>> ExtendedContext.normalize(Decimal('-2.0'))
        Decimal('-2')
        >>> ExtendedContext.normalize(Decimal('1.200'))
        Decimal('1.2')
        >>> ExtendedContext.normalize(Decimal('-120'))
        Decimal('-1.2E+2')
        >>> ExtendedContext.normalize(Decimal('120.00'))
        Decimal('1.2E+2')
        >>> ExtendedContext.normalize(Decimal('0.00'))
        Decimal('0')
        >>> ExtendedContext.normalize(6)
        Decimal('6')
        """
        a = _convert_other(a, raiseit=True)
        return a.normalize(context=self)

    def number_class(self, a):
        """Returns an indication of the class of the operand.

        The class is one of the following strings:
          -sNaN
          -NaN
          -Infinity
          -Normal
          -Subnormal
          -Zero
          +Zero
          +Subnormal
          +Normal
          +Infinity

        >>> c = ExtendedContext.copy()
        >>> c.Emin = -999
        >>> c.Emax = 999
        >>> c.number_class(Decimal('Infinity'))
        '+Infinity'
        >>> c.number_class(Decimal('1E-10'))
        '+Normal'
        >>> c.number_class(Decimal('2.50'))
        '+Normal'
        >>> c.number_class(Decimal('0.1E-999'))
        '+Subnormal'
        >>> c.number_class(Decimal('0'))
        '+Zero'
        >>> c.number_class(Decimal('-0'))
        '-Zero'
        >>> c.number_class(Decimal('-0.1E-999'))
        '-Subnormal'
        >>> c.number_class(Decimal('-1E-10'))
        '-Normal'
        >>> c.number_class(Decimal('-2.50'))
        '-Normal'
        >>> c.number_class(Decimal('-Infinity'))
        '-Infinity'
        >>> c.number_class(Decimal('NaN'))
        'NaN'
        >>> c.number_class(Decimal('-NaN'))
        'NaN'
        >>> c.number_class(Decimal('sNaN'))
        'sNaN'
        >>> c.number_class(123)
        '+Normal'
        """
        a = _convert_other(a, raiseit=True)
        return a.number_class(context=self)

    def plus(self, a):
        """Plus corresponds to unary prefix plus in Python.

        The operation is evaluated using the same rules as add; the
        operation plus(a) is calculated as add('0', a) where the '0'
        has the same exponent as the operand.

        >>> ExtendedContext.plus(Decimal('1.3'))
        Decimal('1.3')
        >>> ExtendedContext.plus(Decimal('-1.3'))
        Decimal('-1.3')
        >>> ExtendedContext.plus(-1)
        Decimal('-1')
        """
        a = _convert_other(a, raiseit=True)
        return a.__pos__(context=self)

    def power(self, a, b, modulo=None):
        """Raises a to the power of b, to modulo if given.

        With two arguments, compute a**b.  If a is negative then b
        must be integral.  The result will be inexact unless b is
        integral and the result is finite and can be expressed exactly
        in 'precision' digits.

        With three arguments, compute (a**b) % modulo.  For the
        three argument form, the following restrictions on the
        arguments hold:

         - all three arguments must be integral
         - b must be nonnegative
         - at least one of a or b must be nonzero
         - modulo must be nonzero and have at most 'precision' digits

        The result of pow(a, b, modulo) is identical to the result
        that would be obtained by computing (a**b) % modulo with
        unbounded precision, but is computed more efficiently.  It is
        always exact.

        >>> c = ExtendedContext.copy()
        >>> c.Emin = -999
        >>> c.Emax = 999
        >>> c.power(Decimal('2'), Decimal('3'))
        Decimal('8')
        >>> c.power(Decimal('-2'), Decimal('3'))
        Decimal('-8')
        >>> c.power(Decimal('2'), Decimal('-3'))
        Decimal('0.125')
        >>> c.power(Decimal('1.7'), Decimal('8'))
        Decimal('69.7575744')
        >>> c.power(Decimal('10'), Decimal('0.301029996'))
        Decimal('2.00000000')
        >>> c.power(Decimal('Infinity'), Decimal('-1'))
        Decimal('0')
        >>> c.power(Decimal('Infinity'), Decimal('0'))
        Decimal('1')
        >>> c.power(Decimal('Infinity'), Decimal('1'))
        Decimal('Infinity')
        >>> c.power(Decimal('-Infinity'), Decimal('-1'))
        Decimal('-0')
        >>> c.power(Decimal('-Infinity'), Decimal('0'))
        Decimal('1')
        >>> c.power(Decimal('-Infinity'), Decimal('1'))
        Decimal('-Infinity')
        >>> c.power(Decimal('-Infinity'), Decimal('2'))
        Decimal('Infinity')
        >>> c.power(Decimal('0'), Decimal('0'))
        Decimal('NaN')

        >>> c.power(Decimal('3'), Decimal('7'), Decimal('16'))
        Decimal('11')
        >>> c.power(Decimal('-3'), Decimal('7'), Decimal('16'))
        Decimal('-11')
        >>> c.power(Decimal('-3'), Decimal('8'), Decimal('16'))
        Decimal('1')
        >>> c.power(Decimal('3'), Decimal('7'), Decimal('-16'))
        Decimal('11')
        >>> c.power(Decimal('23E12345'), Decimal('67E189'), Decimal('123456789'))
        Decimal('11729830')
        >>> c.power(Decimal('-0'), Decimal('17'), Decimal('1729'))
        Decimal('-0')
        >>> c.power(Decimal('-23'), Decimal('0'), Decimal('65537'))
        Decimal('1')
        >>> ExtendedContext.power(7, 7)
        Decimal('823543')
        >>> ExtendedContext.power(Decimal(7), 7)
        Decimal('823543')
        >>> ExtendedContext.power(7, Decimal(7), 2)
        Decimal('1')
        """
        a = _convert_other(a, raiseit=True)
        r = a.__pow__(b, modulo, context=self)
        if r is NotImplemented:
            raise TypeError("Unable to convert %s to Decimal" % b)
        else:
            return r

    def quantize(self, a, b):
        """Returns a value equal to 'a' (rounded), having the exponent of 'b'.

        The coefficient of the result is derived from that of the left-hand
        operand.  It may be rounded using the current rounding setting (if the
        exponent is being increased), multiplied by a positive power of ten (if
        the exponent is being decreased), or is unchanged (if the exponent is
        already equal to that of the right-hand operand).

        Unlike other operations, if the length of the coefficient after the
        quantize operation would be greater than precision then an Invalid
        operation condition is raised.  This guarantees that, unless there is
        an error condition, the exponent of the result of a quantize is always
        equal to that of the right-hand operand.

        Also unlike other operations, quantize will never raise Underflow, even
        if the result is subnormal and inexact.

        >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('0.001'))
        Decimal('2.170')
        >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('0.01'))
        Decimal('2.17')
        >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('0.1'))
        Decimal('2.2')
        >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('1e+0'))
        Decimal('2')
        >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('1e+1'))
        Decimal('0E+1')
        >>> ExtendedContext.quantize(Decimal('-Inf'), Decimal('Infinity'))
        Decimal('-Infinity')
        >>> ExtendedContext.quantize(Decimal('2'), Decimal('Infinity'))
        Decimal('NaN')
        >>> ExtendedContext.quantize(Decimal('-0.1'), Decimal('1'))
        Decimal('-0')
        >>> ExtendedContext.quantize(Decimal('-0'), Decimal('1e+5'))
        Decimal('-0E+5')
        >>> ExtendedContext.quantize(Decimal('+35236450.6'), Decimal('1e-2'))
        Decimal('NaN')
        >>> ExtendedContext.quantize(Decimal('-35236450.6'), Decimal('1e-2'))
        Decimal('NaN')
        >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e-1'))
        Decimal('217.0')
        >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e-0'))
        Decimal('217')
        >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e+1'))
        Decimal('2.2E+2')
        >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e+2'))
        Decimal('2E+2')
        >>> ExtendedContext.quantize(1, 2)
        Decimal('1')
        >>> ExtendedContext.quantize(Decimal(1), 2)
        Decimal('1')
        >>> ExtendedContext.quantize(1, Decimal(2))
        Decimal('1')
        """
        a = _convert_other(a, raiseit=True)
        return a.quantize(b, context=self)

    def radix(self):
        """Just returns 10, as this is Decimal, :)

        >>> ExtendedContext.radix()
        Decimal('10')
        """
        return Decimal(10)

    def remainder(self, a, b):
        """Returns the remainder from integer division.

        The result is the residue of the dividend after the operation of
        calculating integer division as described for divide-integer, rounded
        to precision digits if necessary.  The sign of the result, if
        non-zero, is the same as that of the original dividend.

        This operation will fail under the same conditions as integer division
        (that is, if integer division on the same two operands would fail, the
        remainder cannot be calculated).

        >>> ExtendedContext.remainder(Decimal('2.1'), Decimal('3'))
        Decimal('2.1')
        >>> ExtendedContext.remainder(Decimal('10'), Decimal('3'))
        Decimal('1')
        >>> ExtendedContext.remainder(Decimal('-10'), Decimal('3'))
        Decimal('-1')
        >>> ExtendedContext.remainder(Decimal('10.2'), Decimal('1'))
        Decimal('0.2')
        >>> ExtendedContext.remainder(Decimal('10'), Decimal('0.3'))
        Decimal('0.1')
        >>> ExtendedContext.remainder(Decimal('3.6'), Decimal('1.3'))
        Decimal('1.0')
        >>> ExtendedContext.remainder(22, 6)
        Decimal('4')
        >>> ExtendedContext.remainder(Decimal(22), 6)
        Decimal('4')
        >>> ExtendedContext.remainder(22, Decimal(6))
        Decimal('4')
        """
        a = _convert_other(a, raiseit=True)
        r = a.__mod__(b, context=self)
        if r is NotImplemented:
            raise TypeError("Unable to convert %s to Decimal" % b)
        else:
            return r

    def remainder_near(self, a, b):
        """Returns to be "a - b * n", where n is the integer nearest the exact
        value of "x / b" (if two integers are equally near then the even one
        is chosen).  If the result is equal to 0 then its sign will be the
        sign of a.

        This operation will fail under the same conditions as integer division
        (that is, if integer division on the same two operands would fail, the
        remainder cannot be calculated).

        >>> ExtendedContext.remainder_near(Decimal('2.1'), Decimal('3'))
        Decimal('-0.9')
        >>> ExtendedContext.remainder_near(Decimal('10'), Decimal('6'))
        Decimal('-2')
        >>> ExtendedContext.remainder_near(Decimal('10'), Decimal('3'))
        Decimal('1')
        >>> ExtendedContext.remainder_near(Decimal('-10'), Decimal('3'))
        Decimal('-1')
        >>> ExtendedContext.remainder_near(Decimal('10.2'), Decimal('1'))
        Decimal('0.2')
        >>> ExtendedContext.remainder_near(Decimal('10'), Decimal('0.3'))
        Decimal('0.1')
        >>> ExtendedContext.remainder_near(Decimal('3.6'), Decimal('1.3'))
        Decimal('-0.3')
        >>> ExtendedContext.remainder_near(3, 11)
        Decimal('3')
        >>> ExtendedContext.remainder_near(Decimal(3), 11)
        Decimal('3')
        >>> ExtendedContext.remainder_near(3, Decimal(11))
        Decimal('3')
        """
        a = _convert_other(a, raiseit=True)
        return a.remainder_near(b, context=self)

    def rotate(self, a, b):
        """Returns a rotated copy of a, b times.

        The coefficient of the result is a rotated copy of the digits in
        the coefficient of the first operand.  The number of places of
        rotation is taken from the absolute value of the second operand,
        with the rotation being to the left if the second operand is
        positive or to the right otherwise.

        >>> ExtendedContext.rotate(Decimal('34'), Decimal('8'))
        Decimal('400000003')
        >>> ExtendedContext.rotate(Decimal('12'), Decimal('9'))
        Decimal('12')
        >>> ExtendedContext.rotate(Decimal('123456789'), Decimal('-2'))
        Decimal('891234567')
        >>> ExtendedContext.rotate(Decimal('123456789'), Decimal('0'))
        Decimal('123456789')
        >>> ExtendedContext.rotate(Decimal('123456789'), Decimal('+2'))
        Decimal('345678912')
        >>> ExtendedContext.rotate(1333333, 1)
        Decimal('13333330')
        >>> ExtendedContext.rotate(Decimal(1333333), 1)
        Decimal('13333330')
        >>> ExtendedContext.rotate(1333333, Decimal(1))
        Decimal('13333330')
        """
        a = _convert_other(a, raiseit=True)
        return a.rotate(b, context=self)

    def same_quantum(self, a, b):
        """Returns True if the two operands have the same exponent.

        The result is never affected by either the sign or the coefficient of
        either operand.

        >>> ExtendedContext.same_quantum(Decimal('2.17'), Decimal('0.001'))
        False
        >>> ExtendedContext.same_quantum(Decimal('2.17'), Decimal('0.01'))
        True
        >>> ExtendedContext.same_quantum(Decimal('2.17'), Decimal('1'))
        False
        >>> ExtendedContext.same_quantum(Decimal('Inf'), Decimal('-Inf'))
        True
        >>> ExtendedContext.same_quantum(10000, -1)
        True
        >>> ExtendedContext.same_quantum(Decimal(10000), -1)
        True
        >>> ExtendedContext.same_quantum(10000, Decimal(-1))
        True
        """
        a = _convert_other(a, raiseit=True)
        return a.same_quantum(b)

    def scaleb (self, a, b):
        """Returns the first operand after adding the second value its exp.

        >>> ExtendedContext.scaleb(Decimal('7.50'), Decimal('-2'))
        Decimal('0.0750')
        >>> ExtendedContext.scaleb(Decimal('7.50'), Decimal('0'))
        Decimal('7.50')
        >>> ExtendedContext.scaleb(Decimal('7.50'), Decimal('3'))
        Decimal('7.50E+3')
        >>> ExtendedContext.scaleb(1, 4)
        Decimal('1E+4')
        >>> ExtendedContext.scaleb(Decimal(1), 4)
        Decimal('1E+4')
        >>> ExtendedContext.scaleb(1, Decimal(4))
        Decimal('1E+4')
        """
        a = _convert_other(a, raiseit=True)
        return a.scaleb(b, context=self)

    def shift(self, a, b):
        """Returns a shifted copy of a, b times.

        The coefficient of the result is a shifted copy of the digits
        in the coefficient of the first operand.  The number of places
        to shift is taken from the absolute value of the second operand,
        with the shift being to the left if the second operand is
        positive or to the right otherwise.  Digits shifted into the
        coefficient are zeros.

        >>> ExtendedContext.shift(Decimal('34'), Decimal('8'))
        Decimal('400000000')
        >>> ExtendedContext.shift(Decimal('12'), Decimal('9'))
        Decimal('0')
        >>> ExtendedContext.shift(Decimal('123456789'), Decimal('-2'))
        Decimal('1234567')
        >>> ExtendedContext.shift(Decimal('123456789'), Decimal('0'))
        Decimal('123456789')
        >>> ExtendedContext.shift(Decimal('123456789'), Decimal('+2'))
        Decimal('345678900')
        >>> ExtendedContext.shift(88888888, 2)
        Decimal('888888800')
        >>> ExtendedContext.shift(Decimal(88888888), 2)
        Decimal('888888800')
        >>> ExtendedContext.shift(88888888, Decimal(2))
        Decimal('888888800')
        """
        a = _convert_other(a, raiseit=True)
        return a.shift(b, context=self)

    def sqrt(self, a):
        """Square root of a non-negative number to context precision.

        If the result must be inexact, it is rounded using the round-half-even
        algorithm.

        >>> ExtendedContext.sqrt(Decimal('0'))
        Decimal('0')
        >>> ExtendedContext.sqrt(Decimal('-0'))
        Decimal('-0')
        >>> ExtendedContext.sqrt(Decimal('0.39'))
        Decimal('0.624499800')
        >>> ExtendedContext.sqrt(Decimal('100'))
        Decimal('10')
        >>> ExtendedContext.sqrt(Decimal('1'))
        Decimal('1')
        >>> ExtendedContext.sqrt(Decimal('1.0'))
        Decimal('1.0')
        >>> ExtendedContext.sqrt(Decimal('1.00'))
        Decimal('1.0')
        >>> ExtendedContext.sqrt(Decimal('7'))
        Decimal('2.64575131')
        >>> ExtendedContext.sqrt(Decimal('10'))
        Decimal('3.16227766')
        >>> ExtendedContext.sqrt(2)
        Decimal('1.41421356')
        >>> ExtendedContext.prec
        9
        """
        a = _convert_other(a, raiseit=True)
        return a.sqrt(context=self)

    def subtract(self, a, b):
        """Return the difference between the two operands.

        >>> ExtendedContext.subtract(Decimal('1.3'), Decimal('1.07'))
        Decimal('0.23')
        >>> ExtendedContext.subtract(Decimal('1.3'), Decimal('1.30'))
        Decimal('0.00')
        >>> ExtendedContext.subtract(Decimal('1.3'), Decimal('2.07'))
        Decimal('-0.77')
        >>> ExtendedContext.subtract(8, 5)
        Decimal('3')
        >>> ExtendedContext.subtract(Decimal(8), 5)
        Decimal('3')
        >>> ExtendedContext.subtract(8, Decimal(5))
        Decimal('3')
        """
        a = _convert_other(a, raiseit=True)
        r = a.__sub__(b, context=self)
        if r is NotImplemented:
            raise TypeError("Unable to convert %s to Decimal" % b)
        else:
            return r

    def to_eng_string(self, a):
        """Convert to a string, using engineering notation if an exponent is needed.

        Engineering notation has an exponent which is a multiple of 3.  This
        can leave up to 3 digits to the left of the decimal place and may
        require the addition of either one or two trailing zeros.

        The operation is not affected by the context.

        >>> ExtendedContext.to_eng_string(Decimal('123E+1'))
        '1.23E+3'
        >>> ExtendedContext.to_eng_string(Decimal('123E+3'))
        '123E+3'
        >>> ExtendedContext.to_eng_string(Decimal('123E-10'))
        '12.3E-9'
        >>> ExtendedContext.to_eng_string(Decimal('-123E-12'))
        '-123E-12'
        >>> ExtendedContext.to_eng_string(Decimal('7E-7'))
        '700E-9'
        >>> ExtendedContext.to_eng_string(Decimal('7E+1'))
        '70'
        >>> ExtendedContext.to_eng_string(Decimal('0E+1'))
        '0.00E+3'

        """
        a = _convert_other(a, raiseit=True)
        return a.to_eng_string(context=self)

    def to_sci_string(self, a):
        """Converts a number to a string, using scientific notation.

        The operation is not affected by the context.
        """
        a = _convert_other(a, raiseit=True)
        return a.__str__(context=self)

    def to_integral_exact(self, a):
        """Rounds to an integer.

        When the operand has a negative exponent, the result is the same
        as using the quantize() operation using the given operand as the
        left-hand-operand, 1E+0 as the right-hand-operand, and the precision
        of the operand as the precision setting; Inexact and Rounded flags
        are allowed in this operation.  The rounding mode is taken from the
        context.

        >>> ExtendedContext.to_integral_exact(Decimal('2.1'))
        Decimal('2')
        >>> ExtendedContext.to_integral_exact(Decimal('100'))
        Decimal('100')
        >>> ExtendedContext.to_integral_exact(Decimal('100.0'))
        Decimal('100')
        >>> ExtendedContext.to_integral_exact(Decimal('101.5'))
        Decimal('102')
        >>> ExtendedContext.to_integral_exact(Decimal('-101.5'))
        Decimal('-102')
        >>> ExtendedContext.to_integral_exact(Decimal('10E+5'))
        Decimal('1.0E+6')
        >>> ExtendedContext.to_integral_exact(Decimal('7.89E+77'))
        Decimal('7.89E+77')
        >>> ExtendedContext.to_integral_exact(Decimal('-Inf'))
        Decimal('-Infinity')
        """
        a = _convert_other(a, raiseit=True)
        return a.to_integral_exact(context=self)

    def to_integral_value(self, a):
        """Rounds to an integer.

        When the operand has a negative exponent, the result is the same
        as using the quantize() operation using the given operand as the
        left-hand-operand, 1E+0 as the right-hand-operand, and the precision
        of the operand as the precision setting, except that no flags will
        be set.  The rounding mode is taken from the context.

        >>> ExtendedContext.to_integral_value(Decimal('2.1'))
        Decimal('2')
        >>> ExtendedContext.to_integral_value(Decimal('100'))
        Decimal('100')
        >>> ExtendedContext.to_integral_value(Decimal('100.0'))
        Decimal('100')
        >>> ExtendedContext.to_integral_value(Decimal('101.5'))
        Decimal('102')
        >>> ExtendedContext.to_integral_value(Decimal('-101.5'))
        Decimal('-102')
        >>> ExtendedContext.to_integral_value(Decimal('10E+5'))
        Decimal('1.0E+6')
        >>> ExtendedContext.to_integral_value(Decimal('7.89E+77'))
        Decimal('7.89E+77')
        >>> ExtendedContext.to_integral_value(Decimal('-Inf'))
        Decimal('-Infinity')
        """
        a = _convert_other(a, raiseit=True)
        return a.to_integral_value(context=self)

    # the method name changed, but we provide also the old one, for compatibility
    to_integral = to_integral_value

class _WorkRep(object):
    __slots__ = ('sign','int','exp')
    # sign: 0 or 1
    # int:  int
    # exp:  None, int, or string

    def __init__(self, value=None):
        if value is None:
            self.sign = None
            self.int = 0
            self.exp = None
        elif isinstance(value, Decimal):
            self.sign = value._sign
            self.int = int(value._int)
            self.exp = value._exp
        else:
            # assert isinstance(value, tuple)
            self.sign = value[0]
            self.int = value[1]
            self.exp = value[2]

    def __repr__(self):
        return "(%r, %r, %r)" % (self.sign, self.int, self.exp)



def _normalize(op1, op2, prec = 0):
    """Normalizes op1, op2 to have the same exp and length of coefficient.

    Done during addition.
    """
    if op1.exp < op2.exp:
        tmp = op2
        other = op1
    else:
        tmp = op1
        other = op2

    # Let exp = min(tmp.exp - 1, tmp.adjusted() - precision - 1).
    # Then adding 10**exp to tmp has the same effect (after rounding)
    # as adding any positive quantity smaller than 10**exp; similarly
    # for subtraction.  So if other is smaller than 10**exp we replace
    # it with 10**exp.  This avoids tmp.exp - other.exp getting too large.
    tmp_len = len(str(tmp.int))
    other_len = len(str(other.int))
    exp = tmp.exp + min(-1, tmp_len - prec - 2)
    if other_len + other.exp - 1 < exp:
        other.int = 1
        other.exp = exp

    tmp.int *= 10 ** (tmp.exp - other.exp)
    tmp.exp = other.exp
    return op1, op2

##### Integer arithmetic functions used by ln, log10, exp and __pow__ #####

_nbits = int.bit_length

def _decimal_lshift_exact(n, e):
    """ Given integers n and e, return n * 10**e if it's an integer, else None.

    The computation is designed to avoid computing large powers of 10
    unnecessarily.

    >>> _decimal_lshift_exact(3, 4)
    30000
    >>> _decimal_lshift_exact(300, -999999999)  # returns None

    """
    if n == 0:
        return 0
    elif e >= 0:
        return n * 10**e
    else:
        # val_n = largest power of 10 dividing n.
        str_n = str(abs(n))
        val_n = len(str_n) - len(str_n.rstrip('0'))
        return None if val_n < -e else n // 10**-e

def _sqrt_nearest(n, a):
    """Closest integer to the square root of the positive integer n.  a is
    an initial approximation to the square root.  Any positive integer
    will do for a, but the closer a is to the square root of n the
    faster convergence will be.

    """
    if n <= 0 or a <= 0:
        raise ValueError("Both arguments to _sqrt_nearest should be positive.")

    b=0
    while a != b:
        b, a = a, a--n//a>>1
    return a

def _rshift_nearest(x, shift):
    """Given an integer x and a nonnegative integer shift, return closest
    integer to x / 2**shift; use round-to-even in case of a tie.

    """
    b, q = 1 << shift, x >> shift
    return q + (2*(x & (b-1)) + (q&1) > b)

def _div_nearest(a, b):
    """Closest integer to a/b, a and b positive integers; rounds to even
    in the case of a tie.

    """
    q, r = divmod(a, b)
    return q + (2*r + (q&1) > b)

def _ilog(x, M, L = 8):
    """Integer approximation to M*log(x/M), with absolute error boundable
    in terms only of x/M.

    Given positive integers x and M, return an integer approximation to
    M * log(x/M).  For L = 8 and 0.1 <= x/M <= 10 the difference
    between the approximation and the exact result is at most 22.  For
    L = 8 and 1.0 <= x/M <= 10.0 the difference is at most 15.  In
    both cases these are upper bounds on the error; it will usually be
    much smaller."""

    # The basic algorithm is the following: let log1p be the function
    # log1p(x) = log(1+x).  Then log(x/M) = log1p((x-M)/M).  We use
    # the reduction
    #
    #    log1p(y) = 2*log1p(y/(1+sqrt(1+y)))
    #
    # repeatedly until the argument to log1p is small (< 2**-L in
    # absolute value).  For small y we can use the Taylor series
    # expansion
    #
    #    log1p(y) ~ y - y**2/2 + y**3/3 - ... - (-y)**T/T
    #
    # truncating at T such that y**T is small enough.  The whole
    # computation is carried out in a form of fixed-point arithmetic,
    # with a real number z being represented by an integer
    # approximation to z*M.  To avoid loss of precision, the y below
    # is actually an integer approximation to 2**R*y*M, where R is the
    # number of reductions performed so far.

    y = x-M
    # argument reduction; R = number of reductions performed
    R = 0
    while (R <= L and abs(y) << L-R >= M or
           R > L and abs(y) >> R-L >= M):
        y = _div_nearest((M*y) << 1,
                         M + _sqrt_nearest(M*(M+_rshift_nearest(y, R)), M))
        R += 1

    # Taylor series with T terms
    T = -int(-10*len(str(M))//(3*L))
    yshift = _rshift_nearest(y, R)
    w = _div_nearest(M, T)
    for k in range(T-1, 0, -1):
        w = _div_nearest(M, k) - _div_nearest(yshift*w, M)

    return _div_nearest(w*y, M)

def _dlog10(c, e, p):
    """Given integers c, e and p with c > 0, p >= 0, compute an integer
    approximation to 10**p * log10(c*10**e), with an absolute error of
    at most 1.  Assumes that c*10**e is not exactly 1."""

    # increase precision by 2; compensate for this by dividing
    # final result by 100
    p += 2

    # write c*10**e as d*10**f with either:
    #   f >= 0 and 1 <= d <= 10, or
    #   f <= 0 and 0.1 <= d <= 1.
    # Thus for c*10**e close to 1, f = 0
    l = len(str(c))
    f = e+l - (e+l >= 1)

    if p > 0:
        M = 10**p
        k = e+p-f
        if k >= 0:
            c *= 10**k
        else:
            c = _div_nearest(c, 10**-k)

        log_d = _ilog(c, M) # error < 5 + 22 = 27
        log_10 = _log10_digits(p) # error < 1
        log_d = _div_nearest(log_d*M, log_10)
        log_tenpower = f*M # exact
    else:
        log_d = 0  # error < 2.31
        log_tenpower = _div_nearest(f, 10**-p) # error < 0.5

    return _div_nearest(log_tenpower+log_d, 100)

def _dlog(c, e, p):
    """Given integers c, e and p with c > 0, compute an integer
    approximation to 10**p * log(c*10**e), with an absolute error of
    at most 1.  Assumes that c*10**e is not exactly 1."""

    # Increase precision by 2. The precision increase is compensated
    # for at the end with a division by 100.
    p += 2

    # rewrite c*10**e as d*10**f with either f >= 0 and 1 <= d <= 10,
    # or f <= 0 and 0.1 <= d <= 1.  Then we can compute 10**p * log(c*10**e)
    # as 10**p * log(d) + 10**p*f * log(10).
    l = len(str(c))
    f = e+l - (e+l >= 1)

    # compute approximation to 10**p*log(d), with error < 27
    if p > 0:
        k = e+p-f
        if k >= 0:
            c *= 10**k
        else:
            c = _div_nearest(c, 10**-k)  # error of <= 0.5 in c

        # _ilog magnifies existing error in c by a factor of at most 10
        log_d = _ilog(c, 10**p) # error < 5 + 22 = 27
    else:
        # p <= 0: just approximate the whole thing by 0; error < 2.31
        log_d = 0

    # compute approximation to f*10**p*log(10), with error < 11.
    if f:
        extra = len(str(abs(f)))-1
        if p + extra >= 0:
            # error in f * _log10_digits(p+extra) < |f| * 1 = |f|
            # after division, error < |f|/10**extra + 0.5 < 10 + 0.5 < 11
            f_log_ten = _div_nearest(f*_log10_digits(p+extra), 10**extra)
        else:
            f_log_ten = 0
    else:
        f_log_ten = 0

    # error in sum < 11+27 = 38; error after division < 0.38 + 0.5 < 1
    return _div_nearest(f_log_ten + log_d, 100)

class _Log10Memoize(object):
    """Class to compute, store, and allow retrieval of, digits of the
    constant log(10) = 2.302585....  This constant is needed by
    Decimal.ln, Decimal.log10, Decimal.exp and Decimal.__pow__."""
    def __init__(self):
        self.digits = "23025850929940456840179914546843642076011014886"

    def getdigits(self, p):
        """Given an integer p >= 0, return floor(10**p)*log(10).

        For example, self.getdigits(3) returns 2302.
        """
        # digits are stored as a string, for quick conversion to
        # integer in the case that we've already computed enough
        # digits; the stored digits should always be correct
        # (truncated, not rounded to nearest).
        if p < 0:
            raise ValueError("p should be nonnegative")

        if p >= len(self.digits):
            # compute p+3, p+6, p+9, ... digits; continue until at
            # least one of the extra digits is nonzero
            extra = 3
            while True:
                # compute p+extra digits, correct to within 1ulp
                M = 10**(p+extra+2)
                digits = str(_div_nearest(_ilog(10*M, M), 100))
                if digits[-extra:] != '0'*extra:
                    break
                extra += 3
            # keep all reliable digits so far; remove trailing zeros
            # and next nonzero digit
            self.digits = digits.rstrip('0')[:-1]
        return int(self.digits[:p+1])

_log10_digits = _Log10Memoize().getdigits

def _iexp(x, M, L=8):
    """Given integers x and M, M > 0, such that x/M is small in absolute
    value, compute an integer approximation to M*exp(x/M).  For 0 <=
    x/M <= 2.4, the absolute error in the result is bounded by 60 (and
    is usually much smaller)."""

    # Algorithm: to compute exp(z) for a real number z, first divide z
    # by a suitable power R of 2 so that |z/2**R| < 2**-L.  Then
    # compute expm1(z/2**R) = exp(z/2**R) - 1 using the usual Taylor
    # series
    #
    #     expm1(x) = x + x**2/2! + x**3/3! + ...
    #
    # Now use the identity
    #
    #     expm1(2x) = expm1(x)*(expm1(x)+2)
    #
    # R times to compute the sequence expm1(z/2**R),
    # expm1(z/2**(R-1)), ... , exp(z/2), exp(z).

    # Find R such that x/2**R/M <= 2**-L
    R = _nbits((x<<L)//M)

    # Taylor series.  (2**L)**T > M
    T = -int(-10*len(str(M))//(3*L))
    y = _div_nearest(x, T)
    Mshift = M<<R
    for i in range(T-1, 0, -1):
        y = _div_nearest(x*(Mshift + y), Mshift * i)

    # Expansion
    for k in range(R-1, -1, -1):
        Mshift = M<<(k+2)
        y = _div_nearest(y*(y+Mshift), Mshift)

    return M+y

def _dexp(c, e, p):
    """Compute an approximation to exp(c*10**e), with p decimal places of
    precision.

    Returns integers d, f such that:

      10**(p-1) <= d <= 10**p, and
      (d-1)*10**f < exp(c*10**e) < (d+1)*10**f

    In other words, d*10**f is an approximation to exp(c*10**e) with p
    digits of precision, and with an error in d of at most 1.  This is
    almost, but not quite, the same as the error being < 1ulp: when d
    = 10**(p-1) the error could be up to 10 ulp."""

    # we'll call iexp with M = 10**(p+2), giving p+3 digits of precision
    p += 2

    # compute log(10) with extra precision = adjusted exponent of c*10**e
    extra = max(0, e + len(str(c)) - 1)
    q = p + extra

    # compute quotient c*10**e/(log(10)) = c*10**(e+q)/(log(10)*10**q),
    # rounding down
    shift = e+q
    if shift >= 0:
        cshift = c*10**shift
    else:
        cshift = c//10**-shift
    quot, rem = divmod(cshift, _log10_digits(q))

    # reduce remainder back to original precision
    rem = _div_nearest(rem, 10**extra)

    # error in result of _iexp < 120;  error after division < 0.62
    return _div_nearest(_iexp(rem, 10**p), 1000), quot - p + 3

def _dpower(xc, xe, yc, ye, p):
    """Given integers xc, xe, yc and ye representing Decimals x = xc*10**xe and
    y = yc*10**ye, compute x**y.  Returns a pair of integers (c, e) such that:

      10**(p-1) <= c <= 10**p, and
      (c-1)*10**e < x**y < (c+1)*10**e

    in other words, c*10**e is an approximation to x**y with p digits
    of precision, and with an error in c of at most 1.  (This is
    almost, but not quite, the same as the error being < 1ulp: when c
    == 10**(p-1) we can only guarantee error < 10ulp.)

    We assume that: x is positive and not equal to 1, and y is nonzero.
    """

    # Find b such that 10**(b-1) <= |y| <= 10**b
    b = len(str(abs(yc))) + ye

    # log(x) = lxc*10**(-p-b-1), to p+b+1 places after the decimal point
    lxc = _dlog(xc, xe, p+b+1)

    # compute product y*log(x) = yc*lxc*10**(-p-b-1+ye) = pc*10**(-p-1)
    shift = ye-b
    if shift >= 0:
        pc = lxc*yc*10**shift
    else:
        pc = _div_nearest(lxc*yc, 10**-shift)

    if pc == 0:
        # we prefer a result that isn't exactly 1; this makes it
        # easier to compute a correctly rounded result in __pow__
        if ((len(str(xc)) + xe >= 1) == (yc > 0)): # if x**y > 1:
            coeff, exp = 10**(p-1)+1, 1-p
        else:
            coeff, exp = 10**p-1, -p
    else:
        coeff, exp = _dexp(pc, -(p+1), p+1)
        coeff = _div_nearest(coeff, 10)
        exp += 1

    return coeff, exp

def _log10_lb(c, correction = {
        '1': 100, '2': 70, '3': 53, '4': 40, '5': 31,
        '6': 23, '7': 16, '8': 10, '9': 5}):
    """Compute a lower bound for 100*log10(c) for a positive integer c."""
    if c <= 0:
        raise ValueError("The argument to _log10_lb should be nonnegative.")
    str_c = str(c)
    return 100*len(str_c) - correction[str_c[0]]

##### Helper Functions ####################################################

def _convert_other(other, raiseit=False, allow_float=False):
    """Convert other to Decimal.

    Verifies that it's ok to use in an implicit construction.
    If allow_float is true, allow conversion from float;  this
    is used in the comparison methods (__eq__ and friends).

    """
    if isinstance(other, Decimal):
        return other
    if isinstance(other, int):
        return Decimal(other)
    if allow_float and isinstance(other, float):
        return Decimal.from_float(other)

    if raiseit:
        raise TypeError("Unable to convert %s to Decimal" % other)
    return NotImplemented

def _convert_for_comparison(self, other, equality_op=False):
    """Given a Decimal instance self and a Python object other, return
    a pair (s, o) of Decimal instances such that "s op o" is
    equivalent to "self op other" for any of the 6 comparison
    operators "op".

    """
    if isinstance(other, Decimal):
        return self, other

    # Comparison with a Rational instance (also includes integers):
    # self op n/d <=> self*d op n (for n and d integers, d positive).
    # A NaN or infinity can be left unchanged without affecting the
    # comparison result.
    if isinstance(other, _numbers.Rational):
        if not self._is_special:
            self = _dec_from_triple(self._sign,
                                    str(int(self._int) * other.denominator),
                                    self._exp)
        return self, Decimal(other.numerator)

    # Comparisons with float and complex types.  == and != comparisons
    # with complex numbers should succeed, returning either True or False
    # as appropriate.  Other comparisons return NotImplemented.
    if equality_op and isinstance(other, _numbers.Complex) and other.imag == 0:
        other = other.real
    if isinstance(other, float):
        context = getcontext()
        if equality_op:
            context.flags[FloatOperation] = 1
        else:
            context._raise_error(FloatOperation,
                "strict semantics for mixing floats and Decimals are enabled")
        return self, Decimal.from_float(other)
    return NotImplemented, NotImplemented


##### Setup Specific Contexts ############################################

# The default context prototype used by Context()
# Is mutable, so that new contexts can have different default values

DefaultContext = Context(
        prec=28, rounding=ROUND_HALF_EVEN,
        traps=[DivisionByZero, Overflow, InvalidOperation],
        flags=[],
        Emax=999999,
        Emin=-999999,
        capitals=1,
        clamp=0
)

# Pre-made alternate contexts offered by the specification
# Don't change these; the user should be able to select these
# contexts and be able to reproduce results from other implementations
# of the spec.

BasicContext = Context(
        prec=9, rounding=ROUND_HALF_UP,
        traps=[DivisionByZero, Overflow, InvalidOperation, Clamped, Underflow],
        flags=[],
)

ExtendedContext = Context(
        prec=9, rounding=ROUND_HALF_EVEN,
        traps=[],
        flags=[],
)


##### crud for parsing strings #############################################
#
# Regular expression used for parsing numeric strings.  Additional
# comments:
#
# 1. Uncomment the two '\s*' lines to allow leading and/or trailing
# whitespace.  But note that the specification disallows whitespace in
# a numeric string.
#
# 2. For finite numbers (not infinities and NaNs) the body of the
# number between the optional sign and the optional exponent must have
# at least one decimal digit, possibly after the decimal point.  The
# lookahead expression '(?=\d|\.\d)' checks this.

import re
_parser = re.compile(r"""        # A numeric string consists of:
#    \s*
    (?P<sign>[-+])?              # an optional sign, followed by either...
    (
        (?=\d|\.\d)              # ...a number (with at least one digit)
        (?P<int>\d*)             # having a (possibly empty) integer part
        (\.(?P<frac>\d*))?       # followed by an optional fractional part
        (E(?P<exp>[-+]?\d+))?    # followed by an optional exponent, or...
    |
        Inf(inity)?              # ...an infinity, or...
    |
        (?P<signal>s)?           # ...an (optionally signaling)
        NaN                      # NaN
        (?P<diag>\d*)            # with (possibly empty) diagnostic info.
    )
#    \s*
    \Z
""", re.VERBOSE | re.IGNORECASE).match

_all_zeros = re.compile('0*$').match
_exact_half = re.compile('50*$').match

##### PEP3101 support functions ##############################################
# The functions in this section have little to do with the Decimal
# class, and could potentially be reused or adapted for other pure
# Python numeric classes that want to implement __format__
#
# A format specifier for Decimal looks like:
#
#   [[fill]align][sign][z][#][0][minimumwidth][,][.precision][type]

_parse_format_specifier_regex = re.compile(r"""\A
(?:
   (?P<fill>.)?
   (?P<align>[<>=^])
)?
(?P<sign>[-+ ])?
(?P<no_neg_0>z)?
(?P<alt>\#)?
(?P<zeropad>0)?
(?P<minimumwidth>(?!0)\d+)?
(?P<thousands_sep>,)?
(?:\.(?P<precision>0|(?!0)\d+))?
(?P<type>[eEfFgGn%])?
\Z
""", re.VERBOSE|re.DOTALL)

del re

# The locale module is only needed for the 'n' format specifier.  The
# rest of the PEP 3101 code functions quite happily without it, so we
# don't care too much if locale isn't present.
try:
    import locale as _locale
except ImportError:
    pass

def _parse_format_specifier(format_spec, _localeconv=None):
    """Parse and validate a format specifier.

    Turns a standard numeric format specifier into a dict, with the
    following entries:

      fill: fill character to pad field to minimum width
      align: alignment type, either '<', '>', '=' or '^'
      sign: either '+', '-' or ' '
      minimumwidth: nonnegative integer giving minimum width
      zeropad: boolean, indicating whether to pad with zeros
      thousands_sep: string to use as thousands separator, or ''
      grouping: grouping for thousands separators, in format
        used by localeconv
      decimal_point: string to use for decimal point
      precision: nonnegative integer giving precision, or None
      type: one of the characters 'eEfFgG%', or None

    """
    m = _parse_format_specifier_regex.match(format_spec)
    if m is None:
        raise ValueError("Invalid format specifier: " + format_spec)

    # get the dictionary
    format_dict = m.groupdict()

    # zeropad; defaults for fill and alignment.  If zero padding
    # is requested, the fill and align fields should be absent.
    fill = format_dict['fill']
    align = format_dict['align']
    format_dict['zeropad'] = (format_dict['zeropad'] is not None)
    if format_dict['zeropad']:
        if fill is not None:
            raise ValueError("Fill character conflicts with '0'"
                             " in format specifier: " + format_spec)
        if align is not None:
            raise ValueError("Alignment conflicts with '0' in "
                             "format specifier: " + format_spec)
    format_dict['fill'] = fill or ' '
    # PEP 3101 originally specified that the default alignment should
    # be left;  it was later agreed that right-aligned makes more sense
    # for numeric types.  See http://bugs.python.org/issue6857.
    format_dict['align'] = align or '>'

    # default sign handling: '-' for negative, '' for positive
    if format_dict['sign'] is None:
        format_dict['sign'] = '-'

    # minimumwidth defaults to 0; precision remains None if not given
    format_dict['minimumwidth'] = int(format_dict['minimumwidth'] or '0')
    if format_dict['precision'] is not None:
        format_dict['precision'] = int(format_dict['precision'])

    # if format type is 'g' or 'G' then a precision of 0 makes little
    # sense; convert it to 1.  Same if format type is unspecified.
    if format_dict['precision'] == 0:
        if format_dict['type'] is None or format_dict['type'] in 'gGn':
            format_dict['precision'] = 1

    # determine thousands separator, grouping, and decimal separator, and
    # add appropriate entries to format_dict
    if format_dict['type'] == 'n':
        # apart from separators, 'n' behaves just like 'g'
        format_dict['type'] = 'g'
        if _localeconv is None:
            _localeconv = _locale.localeconv()
        if format_dict['thousands_sep'] is not None:
            raise ValueError("Explicit thousands separator conflicts with "
                             "'n' type in format specifier: " + format_spec)
        format_dict['thousands_sep'] = _localeconv['thousands_sep']
        format_dict['grouping'] = _localeconv['grouping']
        format_dict['decimal_point'] = _localeconv['decimal_point']
    else:
        if format_dict['thousands_sep'] is None:
            format_dict['thousands_sep'] = ''
        format_dict['grouping'] = [3, 0]
        format_dict['decimal_point'] = '.'

    return format_dict

def _format_align(sign, body, spec):
    """Given an unpadded, non-aligned numeric string 'body' and sign
    string 'sign', add padding and alignment conforming to the given
    format specifier dictionary 'spec' (as produced by
    parse_format_specifier).

    """
    # how much extra space do we have to play with?
    minimumwidth = spec['minimumwidth']
    fill = spec['fill']
    padding = fill*(minimumwidth - len(sign) - len(body))

    align = spec['align']
    if align == '<':
        result = sign + body + padding
    elif align == '>':
        result = padding + sign + body
    elif align == '=':
        result = sign + padding + body
    elif align == '^':
        half = len(padding)//2
        result = padding[:half] + sign + body + padding[half:]
    else:
        raise ValueError('Unrecognised alignment field')

    return result

def _group_lengths(grouping):
    """Convert a localeconv-style grouping into a (possibly infinite)
    iterable of integers representing group lengths.

    """
    # The result from localeconv()['grouping'], and the input to this
    # function, should be a list of integers in one of the
    # following three forms:
    #
    #   (1) an empty list, or
    #   (2) nonempty list of positive integers + [0]
    #   (3) list of positive integers + [locale.CHAR_MAX], or

    from itertools import chain, repeat
    if not grouping:
        return []
    elif grouping[-1] == 0 and len(grouping) >= 2:
        return chain(grouping[:-1], repeat(grouping[-2]))
    elif grouping[-1] == _locale.CHAR_MAX:
        return grouping[:-1]
    else:
        raise ValueError('unrecognised format for grouping')

def _insert_thousands_sep(digits, spec, min_width=1):
    """Insert thousands separators into a digit string.

    spec is a dictionary whose keys should include 'thousands_sep' and
    'grouping'; typically it's the result of parsing the format
    specifier using _parse_format_specifier.

    The min_width keyword argument gives the minimum length of the
    result, which will be padded on the left with zeros if necessary.

    If necessary, the zero padding adds an extra '0' on the left to
    avoid a leading thousands separator.  For example, inserting
    commas every three digits in '123456', with min_width=8, gives
    '0,123,456', even though that has length 9.

    """

    sep = spec['thousands_sep']
    grouping = spec['grouping']

    groups = []
    for l in _group_lengths(grouping):
        if l <= 0:
            raise ValueError("group length should be positive")
        # max(..., 1) forces at least 1 digit to the left of a separator
        l = min(max(len(digits), min_width, 1), l)
        groups.append('0'*(l - len(digits)) + digits[-l:])
        digits = digits[:-l]
        min_width -= l
        if not digits and min_width <= 0:
            break
        min_width -= len(sep)
    else:
        l = max(len(digits), min_width, 1)
        groups.append('0'*(l - len(digits)) + digits[-l:])
    return sep.join(reversed(groups))

def _format_sign(is_negative, spec):
    """Determine sign character."""

    if is_negative:
        return '-'
    elif spec['sign'] in ' +':
        return spec['sign']
    else:
        return ''

def _format_number(is_negative, intpart, fracpart, exp, spec):
    """Format a number, given the following data:

    is_negative: true if the number is negative, else false
    intpart: string of digits that must appear before the decimal point
    fracpart: string of digits that must come after the point
    exp: exponent, as an integer
    spec: dictionary resulting from parsing the format specifier

    This function uses the information in spec to:
      insert separators (decimal separator and thousands separators)
      format the sign
      format the exponent
      add trailing '%' for the '%' type
      zero-pad if necessary
      fill and align if necessary
    """

    sign = _format_sign(is_negative, spec)

    if fracpart or spec['alt']:
        fracpart = spec['decimal_point'] + fracpart

    if exp != 0 or spec['type'] in 'eE':
        echar = {'E': 'E', 'e': 'e', 'G': 'E', 'g': 'e'}[spec['type']]
        fracpart += "{0}{1:+}".format(echar, exp)
    if spec['type'] == '%':
        fracpart += '%'

    if spec['zeropad']:
        min_width = spec['minimumwidth'] - len(fracpart) - len(sign)
    else:
        min_width = 0
    intpart = _insert_thousands_sep(intpart, spec, min_width)

    return _format_align(sign, intpart+fracpart, spec)


##### Useful Constants (internal use only) ################################

# Reusable defaults
_Infinity = Decimal('Inf')
_NegativeInfinity = Decimal('-Inf')
_NaN = Decimal('NaN')
_Zero = Decimal(0)
_One = Decimal(1)
_NegativeOne = Decimal(-1)

# _SignedInfinity[sign] is infinity w/ that sign
_SignedInfinity = (_Infinity, _NegativeInfinity)

# Constants related to the hash implementation;  hash(x) is based
# on the reduction of x modulo _PyHASH_MODULUS
_PyHASH_MODULUS = sys.hash_info.modulus
# hash values to use for positive and negative infinities, and nans
_PyHASH_INF = sys.hash_info.inf
_PyHASH_NAN = sys.hash_info.nan

# _PyHASH_10INV is the inverse of 10 modulo the prime _PyHASH_MODULUS
_PyHASH_10INV = pow(10, _PyHASH_MODULUS - 2, _PyHASH_MODULUS)
del sys
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              """Base implementation of event loop.

The event loop can be broken up into a multiplexer (the part
responsible for notifying us of I/O events) and the event loop proper,
which wraps a multiplexer with functionality for scheduling callbacks,
immediately or at a given time in the future.

Whenever a public API takes a callback, subsequent positional
arguments will be passed to the callback if/when it is called.  This
avoids the proliferation of trivial lambdas implementing closures.
Keyword arguments for the callback are not supported; this is a
conscious design decision, leaving the door open for keyword arguments
to modify the meaning of the API call itself.
"""

import collections
import collections.abc
import concurrent.futures
import functools
import heapq
import itertools
import os
import socket
import stat
import subprocess
import threading
import time
import traceback
import sys
import warnings
import weakref

try:
    import ssl
except ImportError:  # pragma: no cover
    ssl = None

from . import constants
from . import coroutines
from . import events
from . import exceptions
from . import futures
from . import protocols
from . import sslproto
from . import staggered
from . import tasks
from . import transports
from . import trsock
from .log import logger


__all__ = 'BaseEventLoop','Server',


# Minimum number of _scheduled timer handles before cleanup of
# cancelled handles is performed.
_MIN_SCHEDULED_TIMER_HANDLES = 100

# Minimum fraction of _scheduled timer handles that are cancelled
# before cleanup of cancelled handles is performed.
_MIN_CANCELLED_TIMER_HANDLES_FRACTION = 0.5


_HAS_IPv6 = hasattr(socket, 'AF_INET6')

# Maximum timeout passed to select to avoid OS limitations
MAXIMUM_SELECT_TIMEOUT = 24 * 3600


def _format_handle(handle):
    cb = handle._callback
    if isinstance(getattr(cb, '__self__', None), tasks.Task):
        # format the task
        return repr(cb.__self__)
    else:
        return str(handle)


def _format_pipe(fd):
    if fd == subprocess.PIPE:
        return '<pipe>'
    elif fd == subprocess.STDOUT:
        return '<stdout>'
    else:
        return repr(fd)


def _set_reuseport(sock):
    if not hasattr(socket, 'SO_REUSEPORT'):
        raise ValueError('reuse_port not supported by socket module')
    else:
        try:
            sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
        except OSError:
            raise ValueError('reuse_port not supported by socket module, '
                             'SO_REUSEPORT defined but not implemented.')


def _ipaddr_info(host, port, family, type, proto, flowinfo=0, scopeid=0):
    # Try to skip getaddrinfo if "host" is already an IP. Users might have
    # handled name resolution in their own code and pass in resolved IPs.
    if not hasattr(socket, 'inet_pton'):
        return

    if proto not in {0, socket.IPPROTO_TCP, socket.IPPROTO_UDP} or \
            host is None:
        return None

    if type == socket.SOCK_STREAM:
        proto = socket.IPPROTO_TCP
    elif type == socket.SOCK_DGRAM:
        proto = socket.IPPROTO_UDP
    else:
        return None

    if port is None:
        port = 0
    elif isinstance(port, bytes) and port == b'':
        port = 0
    elif isinstance(port, str) and port == '':
        port = 0
    else:
        # If port's a service name like "http", don't skip getaddrinfo.
        try:
            port = int(port)
        except (TypeError, ValueError):
            return None

    if family == socket.AF_UNSPEC:
        afs = [socket.AF_INET]
        if _HAS_IPv6:
            afs.append(socket.AF_INET6)
    else:
        afs = [family]

    if isinstance(host, bytes):
        host = host.decode('idna')
    if '%' in host:
        # Linux's inet_pton doesn't accept an IPv6 zone index after host,
        # like '::1%lo0'.
        return None

    for af in afs:
        try:
            socket.inet_pton(af, host)
            # The host has already been resolved.
            if _HAS_IPv6 and af == socket.AF_INET6:
                return af, type, proto, '', (host, port, flowinfo, scopeid)
            else:
                return af, type, proto, '', (host, port)
        except OSError:
            pass

    # "host" is not an IP address.
    return None


def _interleave_addrinfos(addrinfos, first_address_family_count=1):
    """Interleave list of addrinfo tuples by family."""
    # Group addresses by family
    addrinfos_by_family = collections.OrderedDict()
    for addr in addrinfos:
        family = addr[0]
        if family not in addrinfos_by_family:
            addrinfos_by_family[family] = []
        addrinfos_by_family[family].append(addr)
    addrinfos_lists = list(addrinfos_by_family.values())

    reordered = []
    if first_address_family_count > 1:
        reordered.extend(addrinfos_lists[0][:first_address_family_count - 1])
        del addrinfos_lists[0][:first_address_family_count - 1]
    reordered.extend(
        a for a in itertools.chain.from_iterable(
            itertools.zip_longest(*addrinfos_lists)
        ) if a is not None)
    return reordered


def _run_until_complete_cb(fut):
    if not fut.cancelled():
        exc = fut.exception()
        if isinstance(exc, (SystemExit, KeyboardInterrupt)):
            # Issue #22429: run_forever() already finished, no need to
            # stop it.
            return
    futures._get_loop(fut).stop()


if hasattr(socket, 'TCP_NODELAY'):
    def _set_nodelay(sock):
        if (sock.family in {socket.AF_INET, socket.AF_INET6} and
                sock.type == socket.SOCK_STREAM and
                sock.proto == socket.IPPROTO_TCP):
            sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
else:
    def _set_nodelay(sock):
        pass


def _check_ssl_socket(sock):
    if ssl is not None and isinstance(sock, ssl.SSLSocket):
        raise TypeError("Socket cannot be of type SSLSocket")


class _SendfileFallbackProtocol(protocols.Protocol):
    def __init__(self, transp):
        if not isinstance(transp, transports._FlowControlMixin):
            raise TypeError("transport should be _FlowControlMixin instance")
        self._transport = transp
        self._proto = transp.get_protocol()
        self._should_resume_reading = transp.is_reading()
        self._should_resume_writing = transp._protocol_paused
        transp.pause_reading()
        transp.set_protocol(self)
        if self._should_resume_writing:
            self._write_ready_fut = self._transport._loop.create_future()
        else:
            self._write_ready_fut = None

    async def drain(self):
        if self._transport.is_closing():
            raise ConnectionError("Connection closed by peer")
        fut = self._write_ready_fut
        if fut is None:
            return
        await fut

    def connection_made(self, transport):
        raise RuntimeError("Invalid state: "
                           "connection should have been established already.")

    def connection_lost(self, exc):
        if self._write_ready_fut is not None:
            # Never happens if peer disconnects after sending the whole content
            # Thus disconnection is always an exception from user perspective
            if exc is None:
                self._write_ready_fut.set_exception(
                    ConnectionError("Connection is closed by peer"))
            else:
                self._write_ready_fut.set_exception(exc)
        self._proto.connection_lost(exc)

    def pause_writing(self):
        if self._write_ready_fut is not None:
            return
        self._write_ready_fut = self._transport._loop.create_future()

    def resume_writing(self):
        if self._write_ready_fut is None:
            return
        self._write_ready_fut.set_result(False)
        self._write_ready_fut = None

    def data_received(self, data):
        raise RuntimeError("Invalid state: reading should be paused")

    def eof_received(self):
        raise RuntimeError("Invalid state: reading should be paused")

    async def restore(self):
        self._transport.set_protocol(self._proto)
        if self._should_resume_reading:
            self._transport.resume_reading()
        if self._write_ready_fut is not None:
            # Cancel the future.
            # Basically it has no effect because protocol is switched back,
            # no code should wait for it anymore.
            self._write_ready_fut.cancel()
        if self._should_resume_writing:
            self._proto.resume_writing()


class Server(events.AbstractServer):

    def __init__(self, loop, sockets, protocol_factory, ssl_context, backlog,
                 ssl_handshake_timeout, ssl_shutdown_timeout=None):
        self._loop = loop
        self._sockets = sockets
        self._active_count = 0
        self._waiters = []
        self._protocol_factory = protocol_factory
        self._backlog = backlog
        self._ssl_context = ssl_context
        self._ssl_handshake_timeout = ssl_handshake_timeout
        self._ssl_shutdown_timeout = ssl_shutdown_timeout
        self._serving = False
        self._serving_forever_fut = None

    def __repr__(self):
        return f'<{self.__class__.__name__} sockets={self.sockets!r}>'

    def _attach(self):
        assert self._sockets is not None
        self._active_count += 1

    def _detach(self):
        assert self._active_count > 0
        self._active_count -= 1
        if self._active_count == 0 and self._sockets is None:
            self._wakeup()

    def _wakeup(self):
        waiters = self._waiters
        self._waiters = None
        for waiter in waiters:
            if not waiter.done():
                waiter.set_result(waiter)

    def _start_serving(self):
        if self._serving:
            return
        self._serving = True
        for sock in self._sockets:
            sock.listen(self._backlog)
            self._loop._start_serving(
                self._protocol_factory, sock, self._ssl_context,
                self, self._backlog, self._ssl_handshake_timeout,
                self._ssl_shutdown_timeout)

    def get_loop(self):
        return self._loop

    def is_serving(self):
        return self._serving

    @property
    def sockets(self):
        if self._sockets is None:
            return ()
        return tuple(trsock.TransportSocket(s) for s in self._sockets)

    def close(self):
        sockets = self._sockets
        if sockets is None:
            return
        self._sockets = None

        for sock in sockets:
            self._loop._stop_serving(sock)

        self._serving = False

        if (self._serving_forever_fut is not None and
                not self._serving_forever_fut.done()):
            self._serving_forever_fut.cancel()
            self._serving_forever_fut = None

        if self._active_count == 0:
            self._wakeup()

    async def start_serving(self):
        self._start_serving()
        # Skip one loop iteration so that all 'loop.add_reader'
        # go through.
        await tasks.sleep(0)

    async def serve_forever(self):
        if self._serving_forever_fut is not None:
            raise RuntimeError(
                f'server {self!r} is already being awaited on serve_forever()')
        if self._sockets is None:
            raise RuntimeError(f'server {self!r} is closed')

        self._start_serving()
        self._serving_forever_fut = self._loop.create_future()

        try:
            await self._serving_forever_fut
        except exceptions.CancelledError:
            try:
                self.close()
                await self.wait_closed()
            finally:
                raise
        finally:
            self._serving_forever_fut = None

    async def wait_closed(self):
        if self._sockets is None or self._waiters is None:
            return
        waiter = self._loop.create_future()
        self._waiters.append(waiter)
        await waiter


class BaseEventLoop(events.AbstractEventLoop):

    def __init__(self):
        self._timer_cancelled_count = 0
        self._closed = False
        self._stopping = False
        self._ready = collections.deque()
        self._scheduled = []
        self._default_executor = None
        self._internal_fds = 0
        # Identifier of the thread running the event loop, or None if the
        # event loop is not running
        self._thread_id = None
        self._clock_resolution = time.get_clock_info('monotonic').resolution
        self._exception_handler = None
        self.set_debug(coroutines._is_debug_mode())
        # In debug mode, if the execution of a callback or a step of a task
        # exceed this duration in seconds, the slow callback/task is logged.
        self.slow_callback_duration = 0.1
        self._current_handle = None
        self._task_factory = None
        self._coroutine_origin_tracking_enabled = False
        self._coroutine_origin_tracking_saved_depth = None

        # A weak set of all asynchronous generators that are
        # being iterated by the loop.
        self._asyncgens = weakref.WeakSet()
        # Set to True when `loop.shutdown_asyncgens` is called.
        self._asyncgens_shutdown_called = False
        # Set to True when `loop.shutdown_default_executor` is called.
        self._executor_shutdown_called = False

    def __repr__(self):
        return (
            f'<{self.__class__.__name__} running={self.is_running()} '
            f'closed={self.is_closed()} debug={self.get_debug()}>'
        )

    def create_future(self):
        """Create a Future object attached to the loop."""
        return futures.Future(loop=self)

    def create_task(self, coro, *, name=None, context=None):
        """Schedule a coroutine object.

        Return a task object.
        """
        self._check_closed()
        if self._task_factory is None:
            task = tasks.Task(coro, loop=self, name=name, context=context)
            if task._source_traceback:
                del task._source_traceback[-1]
        else:
            if context is None:
                # Use legacy API if context is not needed
                task = self._task_factory(self, coro)
            else:
                task = self._task_factory(self, coro, context=context)

            tasks._set_task_name(task, name)

        return task

    def set_task_factory(self, factory):
        """Set a task factory that will be used by loop.create_task().

        If factory is None the default task factory will be set.

        If factory is a callable, it should have a signature matching
        '(loop, coro)', where 'loop' will be a reference to the active
        event loop, 'coro' will be a coroutine object.  The callable
        must return a Future.
        """
        if factory is not None and not callable(factory):
            raise TypeError('task factory must be a callable or None')
        self._task_factory = factory

    def get_task_factory(self):
        """Return a task factory, or None if the default one is in use."""
        return self._task_factory

    def _make_socket_transport(self, sock, protocol, waiter=None, *,
                               extra=None, server=None):
        """Create socket transport."""
        raise NotImplementedError

    def _make_ssl_transport(
            self, rawsock, protocol, sslcontext, waiter=None,
            *, server_side=False, server_hostname=None,
            extra=None, server=None,
            ssl_handshake_timeout=None,
            ssl_shutdown_timeout=None,
            call_connection_made=True):
        """Create SSL transport."""
        raise NotImplementedError

    def _make_datagram_transport(self, sock, protocol,
                                 address=None, waiter=None, extra=None):
        """Create datagram transport."""
        raise NotImplementedError

    def _make_read_pipe_transport(self, pipe, protocol, waiter=None,
                                  extra=None):
        """Create read pipe transport."""
        raise NotImplementedError

    def _make_write_pipe_transport(self, pipe, protocol, waiter=None,
                                   extra=None):
        """Create write pipe transport."""
        raise NotImplementedError

    async def _make_subprocess_transport(self, protocol, args, shell,
                                         stdin, stdout, stderr, bufsize,
                                         extra=None, **kwargs):
        """Create subprocess transport."""
        raise NotImplementedError

    def _write_to_self(self):
        """Write a byte to self-pipe, to wake up the event loop.

        This may be called from a different thread.

        The subclass is responsible for implementing the self-pipe.
        """
        raise NotImplementedError

    def _process_events(self, event_list):
        """Process selector events."""
        raise NotImplementedError

    def _check_closed(self):
        if self._closed:
            raise RuntimeError('Event loop is closed')

    def _check_default_executor(self):
        if self._executor_shutdown_called:
            raise RuntimeError('Executor shutdown has been called')

    def _asyncgen_finalizer_hook(self, agen):
        self._asyncgens.discard(agen)
        if not self.is_closed():
            self.call_soon_threadsafe(self.create_task, agen.aclose())

    def _asyncgen_firstiter_hook(self, agen):
        if self._asyncgens_shutdown_called:
            warnings.warn(
                f"asynchronous generator {agen!r} was scheduled after "
                f"loop.shutdown_asyncgens() call",
                ResourceWarning, source=self)

        self._asyncgens.add(agen)

    async def shutdown_asyncgens(self):
        """Shutdown all active asynchronous generators."""
        self._asyncgens_shutdown_called = True

        if not len(self._asyncgens):
            # If Python version is <3.6 or we don't have any asynchronous
            # generators alive.
            return

        closing_agens = list(self._asyncgens)
        self._asyncgens.clear()

        results = await tasks.gather(
            *[ag.aclose() for ag in closing_agens],
            return_exceptions=True)

        for result, agen in zip(results, closing_agens):
            if isinstance(result, Exception):
                self.call_exception_handler({
                    'message': f'an error occurred during closing of '
                               f'asynchronous generator {agen!r}',
                    'exception': result,
                    'asyncgen': agen
                })

    async def shutdown_default_executor(self):
        """Schedule the shutdown of the default executor."""
        self._executor_shutdown_called = True
        if self._default_executor is None:
            return
        future = self.create_future()
        thread = threading.Thread(target=self._do_shutdown, args=(future,))
        thread.start()
        try:
            await future
        finally:
            thread.join()

    def _do_shutdown(self, future):
        try:
            self._default_executor.shutdown(wait=True)
            if not self.is_closed():
                self.call_soon_threadsafe(future.set_result, None)
        except Exception as ex:
            if not self.is_closed():
                self.call_soon_threadsafe(future.set_exception, ex)

    def _check_running(self):
        if self.is_running():
            raise RuntimeError('This event loop is already running')
        if events._get_running_loop() is not None:
            raise RuntimeError(
                'Cannot run the event loop while another loop is running')

    def run_forever(self):
        """Run until stop() is called."""
        self._check_closed()
        self._check_running()
        self._set_coroutine_origin_tracking(self._debug)

        old_agen_hooks = sys.get_asyncgen_hooks()
        try:
            self._thread_id = threading.get_ident()
            sys.set_asyncgen_hooks(firstiter=self._asyncgen_firstiter_hook,
                                   finalizer=self._asyncgen_finalizer_hook)

            events._set_running_loop(self)
            while True:
                self._run_once()
                if self._stopping:
                    break
        finally:
            self._stopping = False
            self._thread_id = None
            events._set_running_loop(None)
            self._set_coroutine_origin_tracking(False)
            sys.set_asyncgen_hooks(*old_agen_hooks)

    def run_until_complete(self, future):
        """Run until the Future is done.

        If the argument is a coroutine, it is wrapped in a Task.

        WARNING: It would be disastrous to call run_until_complete()
        with the same coroutine twice -- it would wrap it in two
        different Tasks and that can't be good.

        Return the Future's result, or raise its exception.
        """
        self._check_closed()
        self._check_running()

        new_task = not futures.isfuture(future)
        future = tasks.ensure_future(future, loop=self)
        if new_task:
            # An exception is raised if the future didn't complete, so there
            # is no need to log the "destroy pending task" message
            future._log_destroy_pending = False

        future.add_done_callback(_run_until_complete_cb)
        try:
            self.run_forever()
        except:
            if new_task and future.done() and not future.cancelled():
                # The coroutine raised a BaseException. Consume the exception
                # to not log a warning, the caller doesn't have access to the
                # local task.
                future.exception()
            raise
        finally:
            future.remove_done_callback(_run_until_complete_cb)
        if not future.done():
            raise RuntimeError('Event loop stopped before Future completed.')

        return future.result()

    def stop(self):
        """Stop running the event loop.

        Every callback already scheduled will still run.  This simply informs
        run_forever to stop looping after a complete iteration.
        """
        self._stopping = True

    def close(self):
        """Close the event loop.

        This clears the queues and shuts down the executor,
        but does not wait for the executor to finish.

        The event loop must not be running.
        """
        if self.is_running():
            raise RuntimeError("Cannot close a running event loop")
        if self._closed:
            return
        if self._debug:
            logger.debug("Close %r", self)
        self._closed = True
        self._ready.clear()
        self._scheduled.clear()
        self._executor_shutdown_called = True
        executor = self._default_executor
        if executor is not None:
            self._default_executor = None
            executor.shutdown(wait=False)

    def is_closed(self):
        """Returns True if the event loop was closed."""
        return self._closed

    def __del__(self, _warn=warnings.warn):
        if not self.is_closed():
            _warn(f"unclosed event loop {self!r}", ResourceWarning, source=self)
            if not self.is_running():
                self.close()

    def is_running(self):
        """Returns True if the event loop is running."""
        return (self._thread_id is not None)

    def time(self):
        """Return the time according to the event loop's clock.

        This is a float expressed in seconds since an epoch, but the
        epoch, precision, accuracy and drift are unspecified and may
        differ per event loop.
        """
        return time.monotonic()

    def call_later(self, delay, callback, *args, context=None):
        """Arrange for a callback to be called at a given time.

        Return a Handle: an opaque object with a cancel() method that
        can be used to cancel the call.

        The delay can be an int or float, expressed in seconds.  It is
        always relative to the current time.

        Each callback will be called exactly once.  If two callbacks
        are scheduled for exactly the same time, it undefined which
        will be called first.

        Any positional arguments after the callback will be passed to
        the callback when it is called.
        """
        if delay is None:
            raise TypeError('delay must not be None')
        timer = self.call_at(self.time() + delay, callback, *args,
                             context=context)
        if timer._source_traceback:
            del timer._source_traceback[-1]
        return timer

    def call_at(self, when, callback, *args, context=None):
        """Like call_later(), but uses an absolute time.

        Absolute time corresponds to the event loop's time() method.
        """
        if when is None:
            raise TypeError("when cannot be None")
        self._check_closed()
        if self._debug:
            self._check_thread()
            self._check_callback(callback, 'call_at')
        timer = events.TimerHandle(when, callback, args, self, context)
        if timer._source_traceback:
            del timer._source_traceback[-1]
        heapq.heappush(self._scheduled, timer)
        timer._scheduled = True
        return timer

    def call_soon(self, callback, *args, context=None):
        """Arrange for a callback to be called as soon as possible.

        This operates as a FIFO queue: callbacks are called in the
        order in which they are registered.  Each callback will be
        called exactly once.

        Any positional arguments after the callback will be passed to
        the callback when it is called.
        """
        self._check_closed()
        if self._debug:
            self._check_thread()
            self._check_callback(callback, 'call_soon')
        handle = self._call_soon(callback, args, context)
        if handle._source_traceback:
            del handle._source_traceback[-1]
        return handle

    def _check_callback(self, callback, method):
        if (coroutines.iscoroutine(callback) or
                coroutines.iscoroutinefunction(callback)):
            raise TypeError(
                f"coroutines cannot be used with {method}()")
        if not callable(callback):
            raise TypeError(
                f'a callable object was expected by {method}(), '
                f'got {callback!r}')

    def _call_soon(self, callback, args, context):
        handle = events.Handle(callback, args, self, context)
        if handle._source_traceback:
            del handle._source_traceback[-1]
        self._ready.append(handle)
        return handle

    def _check_thread(self):
        """Check that the current thread is the thread running the event loop.

        Non-thread-safe methods of this class make this assumption and will
        likely behave incorrectly when the assumption is violated.

        Should only be called when (self._debug == True).  The caller is
        responsible for checking this condition for performance reasons.
        """
        if self._thread_id is None:
            return
        thread_id = threading.get_ident()
        if thread_id != self._thread_id:
            raise RuntimeError(
                "Non-thread-safe operation invoked on an event loop other "
                "than the current one")

    def call_soon_threadsafe(self, callback, *args, context=None):
        """Like call_soon(), but thread-safe."""
        self._check_closed()
        if self._debug:
            self._check_callback(callback, 'call_soon_threadsafe')
        handle = self._call_soon(callback, args, context)
        if handle._source_traceback:
            del handle._source_traceback[-1]
        self._write_to_self()
        return handle

    def run_in_executor(self, executor, func, *args):
        self._check_closed()
        if self._debug:
            self._check_callback(func, 'run_in_executor')
        if executor is None:
            executor = self._default_executor
            # Only check when the default executor is being used
            self._check_default_executor()
            if executor is None:
                executor = concurrent.futures.ThreadPoolExecutor(
                    thread_name_prefix='asyncio'
                )
                self._default_executor = executor
        return futures.wrap_future(
            executor.submit(func, *args), loop=self)

    def set_default_executor(self, executor):
        if not isinstance(executor, concurrent.futures.ThreadPoolExecutor):
            raise TypeError('executor must be ThreadPoolExecutor instance')
        self._default_executor = executor

    def _getaddrinfo_debug(self, host, port, family, type, proto, flags):
        msg = [f"{host}:{port!r}"]
        if family:
            msg.append(f'family={family!r}')
        if type:
            msg.append(f'type={type!r}')
        if proto:
            msg.append(f'proto={proto!r}')
        if flags:
            msg.append(f'flags={flags!r}')
        msg = ', '.join(msg)
        logger.debug('Get address info %s', msg)

        t0 = self.time()
        addrinfo = socket.getaddrinfo(host, port, family, type, proto, flags)
        dt = self.time() - t0

        msg = f'Getting address info {msg} took {dt * 1e3:.3f}ms: {addrinfo!r}'
        if dt >= self.slow_callback_duration:
            logger.info(msg)
        else:
            logger.debug(msg)
        return addrinfo

    async def getaddrinfo(self, host, port, *,
                          family=0, type=0, proto=0, flags=0):
        if self._debug:
            getaddr_func = self._getaddrinfo_debug
        else:
            getaddr_func = socket.getaddrinfo

        return await self.run_in_executor(
            None, getaddr_func, host, port, family, type, proto, flags)

    async def getnameinfo(self, sockaddr, flags=0):
        return await self.run_in_executor(
            None, socket.getnameinfo, sockaddr, flags)

    async def sock_sendfile(self, sock, file, offset=0, count=None,
                            *, fallback=True):
        if self._debug and sock.gettimeout() != 0:
            raise ValueError("the socket must be non-blocking")
        _check_ssl_socket(sock)
        self._check_sendfile_params(sock, file, offset, count)
        try:
            return await self._sock_sendfile_native(sock, file,
                                                    offset, count)
        except exceptions.SendfileNotAvailableError as exc:
            if not fallback:
                raise
        return await self._sock_sendfile_fallback(sock, file,
                                                  offset, count)

    async def _sock_sendfile_native(self, sock, file, offset, count):
        # NB: sendfile syscall is not supported for SSL sockets and
        # non-mmap files even if sendfile is supported by OS
        raise exceptions.SendfileNotAvailableError(
            f"syscall sendfile is not available for socket {sock!r} "
            f"and file {file!r} combination")

    async def _sock_sendfile_fallback(self, sock, file, offset, count):
        if offset:
            file.seek(offset)
        blocksize = (
            min(count, constants.SENDFILE_FALLBACK_READBUFFER_SIZE)
            if count else constants.SENDFILE_FALLBACK_READBUFFER_SIZE
        )
        buf = bytearray(blocksize)
        total_sent = 0
        try:
            while True:
                if count:
                    blocksize = min(count - total_sent, blocksize)
                    if blocksize <= 0:
                        break
                view = memoryview(buf)[:blocksize]
                read = await self.run_in_executor(None, file.readinto, view)
                if not read:
                    break  # EOF
                await self.sock_sendall(sock, view[:read])
                total_sent += read
            return total_sent
        finally:
            if total_sent > 0 and hasattr(file, 'seek'):
                file.seek(offset + total_sent)

    def _check_sendfile_params(self, sock, file, offset, count):
        if 'b' not in getattr(file, 'mode', 'b'):
            raise ValueError("file should be opened in binary mode")
        if not sock.type == socket.SOCK_STREAM:
            raise ValueError("only SOCK_STREAM type sockets are supported")
        if count is not None:
            if not isinstance(count, int):
                raise TypeError(
                    "count must be a positive integer (got {!r})".format(count))
            if count <= 0:
                raise ValueError(
                    "count must be a positive integer (got {!r})".format(count))
        if not isinstance(offset, int):
            raise TypeError(
                "offset must be a non-negative integer (got {!r})".format(
                    offset))
        if offset < 0:
            raise ValueError(
                "offset must be a non-negative integer (got {!r})".format(
                    offset))

    async def _connect_sock(self, exceptions, addr_info, local_addr_infos=None):
        """Create, bind and connect one socket."""
        my_exceptions = []
        exceptions.append(my_exceptions)
        family, type_, proto, _, address = addr_info
        sock = None
        try:
            sock = socket.socket(family=family, type=type_, proto=proto)
            sock.setblocking(False)
            if local_addr_infos is not None:
                for lfamily, _, _, _, laddr in local_addr_infos:
                    # skip local addresses of different family
                    if lfamily != family:
                        continue
                    try:
                        sock.bind(laddr)
                        break
                    except OSError as exc:
                        msg = (
                            f'error while attempting to bind on '
                            f'address {laddr!r}: '
                            f'{exc.strerror.lower()}'
                        )
                        exc = OSError(exc.errno, msg)
                        my_exceptions.append(exc)
                else:  # all bind attempts failed
                    if my_exceptions:
                        raise my_exceptions.pop()
                    else:
                        raise OSError(f"no matching local address with {family=} found")
            await self.sock_connect(sock, address)
            return sock
        except OSError as exc:
            my_exceptions.append(exc)
            if sock is not None:
                sock.close()
            raise
        except:
            if sock is not None:
                sock.close()
            raise
        finally:
            exceptions = my_exceptions = None

    async def create_connection(
            self, protocol_factory, host=None, port=None,
            *, ssl=None, family=0,
            proto=0, flags=0, sock=None,
            local_addr=None, server_hostname=None,
            ssl_handshake_timeout=None,
            ssl_shutdown_timeout=None,
            happy_eyeballs_delay=None, interleave=None):
        """Connect to a TCP server.

        Create a streaming transport connection to a given internet host and
        port: socket family AF_INET or socket.AF_INET6 depending on host (or
        family if specified), socket type SOCK_STREAM. protocol_factory must be
        a callable returning a protocol instance.

        This method is a coroutine which will try to establish the connection
        in the background.  When successful, the coroutine returns a
        (transport, protocol) pair.
        """
        if server_hostname is not None and not ssl:
            raise ValueError('server_hostname is only meaningful with ssl')

        if server_hostname is None and ssl:
            # Use host as default for server_hostname.  It is an error
            # if host is empty or not set, e.g. when an
            # already-connected socket was passed or when only a port
            # is given.  To avoid this error, you can pass
            # server_hostname='' -- this will bypass the hostname
            # check.  (This also means that if host is a numeric
            # IP/IPv6 address, we will attempt to verify that exact
            # address; this will probably fail, but it is possible to
            # create a certificate for a specific IP address, so we
            # don't judge it here.)
            if not host:
                raise ValueError('You must set server_hostname '
                                 'when using ssl without a host')
            server_hostname = host

        if ssl_handshake_timeout is not None and not ssl:
            raise ValueError(
                'ssl_handshake_timeout is only meaningful with ssl')

        if ssl_shutdown_timeout is not None and not ssl:
            raise ValueError(
                'ssl_shutdown_timeout is only meaningful with ssl')

        if sock is not None:
            _check_ssl_socket(sock)

        if happy_eyeballs_delay is not None and interleave is None:
            # If using happy eyeballs, default to interleave addresses by family
            interleave = 1

        if host is not None or port is not None:
            if sock is not None:
                raise ValueError(
                    'host/port and sock can not be specified at the same time')

            infos = await self._ensure_resolved(
                (host, port), family=family,
                type=socket.SOCK_STREAM, proto=proto, flags=flags, loop=self)
            if not infos:
                raise OSError('getaddrinfo() returned empty list')

            if local_addr is not None:
                laddr_infos = await self._ensure_resolved(
                    local_addr, family=family,
                    type=socket.SOCK_STREAM, proto=proto,
                    flags=flags, loop=self)
                if not laddr_infos:
                    raise OSError('getaddrinfo() returned empty list')
            else:
                laddr_infos = None

            if interleave:
                infos = _interleave_addrinfos(infos, interleave)

            exceptions = []
            if happy_eyeballs_delay is None:
                # not using happy eyeballs
                for addrinfo in infos:
                    try:
                        sock = await self._connect_sock(
                            exceptions, addrinfo, laddr_infos)
                        break
                    except OSError:
                        continue
            else:  # using happy eyeballs
                sock, _, _ = await staggered.staggered_race(
                    (functools.partial(self._connect_sock,
                                       exceptions, addrinfo, laddr_infos)
                     for addrinfo in infos),
                    happy_eyeballs_delay, loop=self)

            if sock is None:
                exceptions = [exc for sub in exceptions for exc in sub]
                try:
                    if len(exceptions) == 1:
                        raise exceptions[0]
                    else:
                        # If they all have the same str(), raise one.
                        model = str(exceptions[0])
                        if all(str(exc) == model for exc in exceptions):
                            raise exceptions[0]
                        # Raise a combined exception so the user can see all
                        # the various error messages.
                        raise OSError('Multiple exceptions: {}'.format(
                            ', '.join(str(exc) for exc in exceptions)))
                finally:
                    exceptions = None

        else:
            if sock is None:
                raise ValueError(
                    'host and port was not specified and no sock specified')
            if sock.type != socket.SOCK_STREAM:
                # We allow AF_INET, AF_INET6, AF_UNIX as long as they
                # are SOCK_STREAM.
                # We support passing AF_UNIX sockets even though we have
                # a dedicated API for that: create_unix_connection.
                # Disallowing AF_UNIX in this method, breaks backwards
                # compatibility.
                raise ValueError(
                    f'A Stream Socket was expected, got {sock!r}')

        transport, protocol = await self._create_connection_transport(
            sock, protocol_factory, ssl, server_hostname,
            ssl_handshake_timeout=ssl_handshake_timeout,
            ssl_shutdown_timeout=ssl_shutdown_timeout)
        if self._debug:
            # Get the socket from the transport because SSL transport closes
            # the old socket and creates a new SSL socket
            sock = transport.get_extra_info('socket')
            logger.debug("%r connected to %s:%r: (%r, %r)",
                         sock, host, port, transport, protocol)
        return transport, protocol

    async def _create_connection_transport(
            self, sock, protocol_factory, ssl,
            server_hostname, server_side=False,
            ssl_handshake_timeout=None,
            ssl_shutdown_timeout=None):

        sock.setblocking(False)

        protocol = protocol_factory()
        waiter = self.create_future()
        if ssl:
            sslcontext = None if isinstance(ssl, bool) else ssl
            transport = self._make_ssl_transport(
                sock, protocol, sslcontext, waiter,
                server_side=server_side, server_hostname=server_hostname,
                ssl_handshake_timeout=ssl_handshake_timeout,
                ssl_shutdown_timeout=ssl_shutdown_timeout)
        else:
            transport = self._make_socket_transport(sock, protocol, waiter)

        try:
            await waiter
        except:
            transport.close()
            raise

        return transport, protocol

    async def sendfile(self, transport, file, offset=0, count=None,
                       *, fallback=True):
        """Send a file to transport.

        Return the total number of bytes which were sent.

        The method uses high-performance os.sendfile if available.

        file must be a regular file object opened in binary mode.

        offset tells from where to start reading the file. If specified,
        count is the total number of bytes to transmit as opposed to
        sending the file until EOF is reached. File position is updated on
        return or also in case of error in which case file.tell()
        can be used to figure out the number of bytes
        which were sent.

        fallback set to True makes asyncio to manually read and send
        the file when the platform does not support the sendfile syscall
        (e.g. Windows or SSL socket on Unix).

        Raise SendfileNotAvailableError if the system does not support
        sendfile syscall and fallback is False.
        """
        if transport.is_closing():
            raise RuntimeError("Transport is closing")
        mode = getattr(transport, '_sendfile_compatible',
                       constants._SendfileMode.UNSUPPORTED)
        if mode is constants._SendfileMode.UNSUPPORTED:
            raise RuntimeError(
                f"sendfile is not supported for transport {transport!r}")
        if mode is constants._SendfileMode.TRY_NATIVE:
            try:
                return await self._sendfile_native(transport, file,
                                                   offset, count)
            except exceptions.SendfileNotAvailableError as exc:
                if not fallback:
                    raise

        if not fallback:
            raise RuntimeError(
                f"fallback is disabled and native sendfile is not "
                f"supported for transport {transport!r}")

        return await self._sendfile_fallback(transport, file,
                                             offset, count)

    async def _sendfile_native(self, transp, file, offset, count):
        raise exceptions.SendfileNotAvailableError(
            "sendfile syscall is not supported")

    async def _sendfile_fallback(self, transp, file, offset, count):
        if offset:
            file.seek(offset)
        blocksize = min(count, 16384) if count else 16384
        buf = bytearray(blocksize)
        total_sent = 0
        proto = _SendfileFallbackProtocol(transp)
        try:
            while True:
                if count:
                    blocksize = min(count - total_sent, blocksize)
                    if blocksize <= 0:
                        return total_sent
                view = memoryview(buf)[:blocksize]
                read = await self.run_in_executor(None, file.readinto, view)
                if not read:
                    return total_sent  # EOF
                await proto.drain()
                transp.write(view[:read])
                total_sent += read
        finally:
            if total_sent > 0 and hasattr(file, 'seek'):
                file.seek(offset + total_sent)
            await proto.restore()

    async def start_tls(self, transport, protocol, sslcontext, *,
                        server_side=False,
                        server_hostname=None,
                        ssl_handshake_timeout=None,
                        ssl_shutdown_timeout=None):
        """Upgrade transport to TLS.

        Return a new transport that *protocol* should start using
        immediately.
        """
        if ssl is None:
            raise RuntimeError('Python ssl module is not available')

        if not isinstance(sslcontext, ssl.SSLContext):
            raise TypeError(
                f'sslcontext is expected to be an instance of ssl.SSLContext, '
                f'got {sslcontext!r}')

        if not getattr(transport, '_start_tls_compatible', False):
            raise TypeError(
                f'transport {transport!r} is not supported by start_tls()')

        waiter = self.create_future()
        ssl_protocol = sslproto.SSLProtocol(
            self, protocol, sslcontext, waiter,
            server_side, server_hostname,
            ssl_handshake_timeout=ssl_handshake_timeout,
            ssl_shutdown_timeout=ssl_shutdown_timeout,
            call_connection_made=False)

        # Pause early so that "ssl_protocol.data_received()" doesn't
        # have a chance to get called before "ssl_protocol.connection_made()".
        transport.pause_reading()

        transport.set_protocol(ssl_protocol)
        conmade_cb = self.call_soon(ssl_protocol.connection_made, transport)
        resume_cb = self.call_soon(transport.resume_reading)

        try:
            await waiter
        except BaseException:
            transport.close()
            conmade_cb.cancel()
            resume_cb.cancel()
            raise

        return ssl_protocol._app_transport

    async def create_datagram_endpoint(self, protocol_factory,
                                       local_addr=None, remote_addr=None, *,
                                       family=0, proto=0, flags=0,
                                       reuse_port=None,
                                       allow_broadcast=None, sock=None):
        """Create datagram connection."""
        if sock is not None:
            if sock.type != socket.SOCK_DGRAM:
                raise ValueError(
                    f'A UDP Socket was expected, got {sock!r}')
            if (local_addr or remote_addr or
                    family or proto or flags or
                    reuse_port or allow_broadcast):
                # show the problematic kwargs in exception msg
                opts = dict(local_addr=local_addr, remote_addr=remote_addr,
                            family=family, proto=proto, flags=flags,
                            reuse_port=reuse_port,
                            allow_broadcast=allow_broadcast)
                problems = ', '.join(f'{k}={v}' for k, v in opts.items() if v)
                raise ValueError(
                    f'socket modifier keyword arguments can not be used '
                    f'when sock is specified. ({problems})')
            sock.setblocking(False)
            r_addr = None
        else:
            if not (local_addr or remote_addr):
                if family == 0:
                    raise ValueError('unexpected address family')
                addr_pairs_info = (((family, proto), (None, None)),)
            elif hasattr(socket, 'AF_UNIX') and family == socket.AF_UNIX:
                for addr in (local_addr, remote_addr):
                    if addr is not None and not isinstance(addr, str):
                        raise TypeError('string is expected')

                if local_addr and local_addr[0] not in (0, '\x00'):
                    try:
                        if stat.S_ISSOCK(os.stat(local_addr).st_mode):
                            os.remove(local_addr)
                    except FileNotFoundError:
                        pass
                    except OSError as err:
                        # Directory may have permissions only to create socket.
                        logger.error('Unable to check or remove stale UNIX '
                                     'socket %r: %r',
                                     local_addr, err)

                addr_pairs_info = (((family, proto),
                                    (local_addr, remote_addr)), )
            else:
                # join address by (family, protocol)
                addr_infos = {}  # Using order preserving dict
                for idx, addr in ((0, local_addr), (1, remote_addr)):
                    if addr is not None:
                        if not (isinstance(addr, tuple) and len(addr) == 2):
                            raise TypeError('2-tuple is expected')

                        infos = await self._ensure_resolved(
                            addr, family=family, type=socket.SOCK_DGRAM,
                            proto=proto, flags=flags, loop=self)
                        if not infos:
                            raise OSError('getaddrinfo() returned empty list')

                        for fam, _, pro, _, address in infos:
                            key = (fam, pro)
                            if key not in addr_infos:
                                addr_infos[key] = [None, None]
                            addr_infos[key][idx] = address

                # each addr has to have info for each (family, proto) pair
                addr_pairs_info = [
                    (key, addr_pair) for key, addr_pair in addr_infos.items()
                    if not ((local_addr and addr_pair[0] is None) or
                            (remote_addr and addr_pair[1] is None))]

                if not addr_pairs_info:
                    raise ValueError('can not get address information')

            exceptions = []

            for ((family, proto),
                 (local_address, remote_address)) in addr_pairs_info:
                sock = None
                r_addr = None
                try:
                    sock = socket.socket(
                        family=family, type=socket.SOCK_DGRAM, proto=proto)
                    if reuse_port:
                        _set_reuseport(sock)
                    if allow_broadcast:
                        sock.setsockopt(
                            socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
                    sock.setblocking(False)

                    if local_addr:
                        sock.bind(local_address)
                    if remote_addr:
                        if not allow_broadcast:
                            await self.sock_connect(sock, remote_address)
                        r_addr = remote_address
                except OSError as exc:
                    if sock is not None:
                        sock.close()
                    exceptions.append(exc)
                except:
                    if sock is not None:
                        sock.close()
                    raise
                else:
                    break
            else:
                raise exceptions[0]

        protocol = protocol_factory()
        waiter = self.create_future()
        transport = self._make_datagram_transport(
            sock, protocol, r_addr, waiter)
        if self._debug:
            if local_addr:
                logger.info("Datagram endpoint local_addr=%r remote_addr=%r "
                            "created: (%r, %r)",
                            local_addr, remote_addr, transport, protocol)
            else:
                logger.debug("Datagram endpoint remote_addr=%r created: "
                             "(%r, %r)",
                             remote_addr, transport, protocol)

        try:
            await waiter
        except:
            transport.close()
            raise

        return transport, protocol

    async def _ensure_resolved(self, address, *,
                               family=0, type=socket.SOCK_STREAM,
                               proto=0, flags=0, loop):
        host, port = address[:2]
        info = _ipaddr_info(host, port, family, type, proto, *address[2:])
        if info is not None:
            # "host" is already a resolved IP.
            return [info]
        else:
            return await loop.getaddrinfo(host, port, family=family, type=type,
                                          proto=proto, flags=flags)

    async def _create_server_getaddrinfo(self, host, port, family, flags):
        infos = await self._ensure_resolved((host, port), family=family,
                                            type=socket.SOCK_STREAM,
                                            flags=flags, loop=self)
        if not infos:
            raise OSError(f'getaddrinfo({host!r}) returned empty list')
        return infos

    async def create_server(
            self, protocol_factory, host=None, port=None,
            *,
            family=socket.AF_UNSPEC,
            flags=socket.AI_PASSIVE,
            sock=None,
            backlog=100,
            ssl=None,
            reuse_address=None,
            reuse_port=None,
            ssl_handshake_timeout=None,
            ssl_shutdown_timeout=None,
            start_serving=True):
        """Create a TCP server.

        The host parameter can be a string, in that case the TCP server is
        bound to host and port.

        The host parameter can also be a sequence of strings and in that case
        the TCP server is bound to all hosts of the sequence. If a host
        appears multiple times (possibly indirectly e.g. when hostnames
        resolve to the same IP address), the server is only bound once to that
        host.

        Return a Server object which can be used to stop the service.

        This method is a coroutine.
        """
        if isinstance(ssl, bool):
            raise TypeError('ssl argument must be an SSLContext or None')

        if ssl_handshake_timeout is not None and ssl is None:
            raise ValueError(
                'ssl_handshake_timeout is only meaningful with ssl')

        if ssl_shutdown_timeout is not None and ssl is None:
            raise ValueError(
                'ssl_shutdown_timeout is only meaningful with ssl')

        if sock is not None:
            _check_ssl_socket(sock)

        if host is not None or port is not None:
            if sock is not None:
                raise ValueError(
                    'host/port and sock can not be specified at the same time')

            if reuse_address is None:
                reuse_address = os.name == "posix" and sys.platform != "cygwin"
            sockets = []
            if host == '':
                hosts = [None]
            elif (isinstance(host, str) or
                  not isinstance(host, collections.abc.Iterable)):
                hosts = [host]
            else:
                hosts = host

            fs = [self._create_server_getaddrinfo(host, port, family=family,
                                                  flags=flags)
                  for host in hosts]
            infos = await tasks.gather(*fs)
            infos = set(itertools.chain.from_iterable(infos))

            completed = False
            try:
                for res in infos:
                    af, socktype, proto, canonname, sa = res
                    try:
                        sock = socket.socket(af, socktype, proto)
                    except socket.error:
                        # Assume it's a bad family/type/protocol combination.
                        if self._debug:
                            logger.warning('create_server() failed to create '
                                           'socket.socket(%r, %r, %r)',
                                           af, socktype, proto, exc_info=True)
                        continue
                    sockets.append(sock)
                    if reuse_address:
                        sock.setsockopt(
                            socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
                    if reuse_port:
                        _set_reuseport(sock)
                    # Disable IPv4/IPv6 dual stack support (enabled by
                    # default on Linux) which makes a single socket
                    # listen on both address families.
                    if (_HAS_IPv6 and
                            af == socket.AF_INET6 and
                            hasattr(socket, 'IPPROTO_IPV6')):
                        sock.setsockopt(socket.IPPROTO_IPV6,
                                        socket.IPV6_V6ONLY,
                                        True)
                    try:
                        sock.bind(sa)
                    except OSError as err:
                        raise OSError(err.errno, 'error while attempting '
                                      'to bind on address %r: %s'
                                      % (sa, err.strerror.lower())) from None
                completed = True
            finally:
                if not completed:
                    for sock in sockets:
                        sock.close()
        else:
            if sock is None:
                raise ValueError('Neither host/port nor sock were specified')
            if sock.type != socket.SOCK_STREAM:
                raise ValueError(f'A Stream Socket was expected, got {sock!r}')
            sockets = [sock]

        for sock in sockets:
            sock.setblocking(False)

        server = Server(self, sockets, protocol_factory,
                        ssl, backlog, ssl_handshake_timeout,
                        ssl_shutdown_timeout)
        if start_serving:
            server._start_serving()
            # Skip one loop iteration so that all 'loop.add_reader'
            # go through.
            await tasks.sleep(0)

        if self._debug:
            logger.info("%r is serving", server)
        return server

    async def connect_accepted_socket(
            self, protocol_factory, sock,
            *, ssl=None,
            ssl_handshake_timeout=None,
            ssl_shutdown_timeout=None):
        if sock.type != socket.SOCK_STREAM:
            raise ValueError(f'A Stream Socket was expected, got {sock!r}')

        if ssl_handshake_timeout is not None and not ssl:
            raise ValueError(
                'ssl_handshake_timeout is only meaningful with ssl')

        if ssl_shutdown_timeout is not None and not ssl:
            raise ValueError(
                'ssl_shutdown_timeout is only meaningful with ssl')

        if sock is not None:
            _check_ssl_socket(sock)

        transport, protocol = await self._create_connection_transport(
            sock, protocol_factory, ssl, '', server_side=True,
            ssl_handshake_timeout=ssl_handshake_timeout,
            ssl_shutdown_timeout=ssl_shutdown_timeout)
        if self._debug:
            # Get the socket from the transport because SSL transport closes
            # the old socket and creates a new SSL socket
            sock = transport.get_extra_info('socket')
            logger.debug("%r handled: (%r, %r)", sock, transport, protocol)
        return transport, protocol

    async def connect_read_pipe(self, protocol_factory, pipe):
        protocol = protocol_factory()
        waiter = self.create_future()
        transport = self._make_read_pipe_transport(pipe, protocol, waiter)

        try:
            await waiter
        except:
            transport.close()
            raise

        if self._debug:
            logger.debug('Read pipe %r connected: (%r, %r)',
                         pipe.fileno(), transport, protocol)
        return transport, protocol

    async def connect_write_pipe(self, protocol_factory, pipe):
        protocol = protocol_factory()
        waiter = self.create_future()
        transport = self._make_write_pipe_transport(pipe, protocol, waiter)

        try:
            await waiter
        except:
            transport.close()
            raise

        if self._debug:
            logger.debug('Write pipe %r connected: (%r, %r)',
                         pipe.fileno(), transport, protocol)
        return transport, protocol

    def _log_subprocess(self, msg, stdin, stdout, stderr):
        info = [msg]
        if stdin is not None:
            info.append(f'stdin={_format_pipe(stdin)}')
        if stdout is not None and stderr == subprocess.STDOUT:
            info.append(f'stdout=stderr={_format_pipe(stdout)}')
        else:
            if stdout is not None:
                info.append(f'stdout={_format_pipe(stdout)}')
            if stderr is not None:
                info.append(f'stderr={_format_pipe(stderr)}')
        logger.debug(' '.join(info))

    async def subprocess_shell(self, protocol_factory, cmd, *,
                               stdin=subprocess.PIPE,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE,
                               universal_newlines=False,
                               shell=True, bufsize=0,
                               encoding=None, errors=None, text=None,
                               **kwargs):
        if not isinstance(cmd, (bytes, str)):
            raise ValueError("cmd must be a string")
        if universal_newlines:
            raise ValueError("universal_newlines must be False")
        if not shell:
            raise ValueError("shell must be True")
        if bufsize != 0:
            raise ValueError("bufsize must be 0")
        if text:
            raise ValueError("text must be False")
        if encoding is not None:
            raise ValueError("encoding must be None")
        if errors is not None:
            raise ValueError("errors must be None")

        protocol = protocol_factory()
        debug_log = None
        if self._debug:
            # don't log parameters: they may contain sensitive information
            # (password) and may be too long
            debug_log = 'run shell command %r' % cmd
            self._log_subprocess(debug_log, stdin, stdout, stderr)
        transport = await self._make_subprocess_transport(
            protocol, cmd, True, stdin, stdout, stderr, bufsize, **kwargs)
        if self._debug and debug_log is not None:
            logger.info('%s: %r', debug_log, transport)
        return transport, protocol

    async def subprocess_exec(self, protocol_factory, program, *args,
                              stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                              stderr=subprocess.PIPE, universal_newlines=False,
                              shell=False, bufsize=0,
                              encoding=None, errors=None, text=None,
                              **kwargs):
        if universal_newlines:
            raise ValueError("universal_newlines must be False")
        if shell:
            raise ValueError("shell must be False")
        if bufsize != 0:
            raise ValueError("bufsize must be 0")
        if text:
            raise ValueError("text must be False")
        if encoding is not None:
            raise ValueError("encoding must be None")
        if errors is not None:
            raise ValueError("errors must be None")

        popen_args = (program,) + args
        protocol = protocol_factory()
        debug_log = None
        if self._debug:
            # don't log parameters: they may contain sensitive information
            # (password) and may be too long
            debug_log = f'execute program {program!r}'
            self._log_subprocess(debug_log, stdin, stdout, stderr)
        transport = await self._make_subprocess_transport(
            protocol, popen_args, False, stdin, stdout, stderr,
            bufsize, **kwargs)
        if self._debug and debug_log is not None:
            logger.info('%s: %r', debug_log, transport)
        return transport, protocol

    def get_exception_handler(self):
        """Return an exception handler, or None if the default one is in use.
        """
        return self._exception_handler

    def set_exception_handler(self, handler):
        """Set handler as the new event loop exception handler.

        If handler is None, the default exception handler will
        be set.

        If handler is a callable object, it should have a
        signature matching '(loop, context)', where 'loop'
        will be a reference to the active event loop, 'context'
        will be a dict object (see `call_exception_handler()`
        documentation for details about context).
        """
        if handler is not None and not callable(handler):
            raise TypeError(f'A callable object or None is expected, '
                            f'got {handler!r}')
        self._exception_handler = handler

    def default_exception_handler(self, context):
        """Default exception handler.

        This is called when an exception occurs and no exception
        handler is set, and can be called by a custom exception
        handler that wants to defer to the default behavior.

        This default handler logs the error message and other
        context-dependent information.  In debug mode, a truncated
        stack trace is also appended showing where the given object
        (e.g. a handle or future or task) was created, if any.

        The context parameter has the same meaning as in
        `call_exception_handler()`.
        """
        message = context.get('message')
        if not message:
            message = 'Unhandled exception in event loop'

        exception = context.get('exception')
        if exception is not None:
            exc_info = (type(exception), exception, exception.__traceback__)
        else:
            exc_info = False

        if ('source_traceback' not in context and
                self._current_handle is not None and
                self._current_handle._source_traceback):
            context['handle_traceback'] = \
                self._current_handle._source_traceback

        log_lines = [message]
        for key in sorted(context):
            if key in {'message', 'exception'}:
                continue
            value = context[key]
            if key == 'source_traceback':
                tb = ''.join(traceback.format_list(value))
                value = 'Object created at (most recent call last):\n'
                value += tb.rstrip()
            elif key == 'handle_traceback':
                tb = ''.join(traceback.format_list(value))
                value = 'Handle created at (most recent call last):\n'
                value += tb.rstrip()
            else:
                value = repr(value)
            log_lines.append(f'{key}: {value}')

        logger.error('\n'.join(log_lines), exc_info=exc_info)

    def call_exception_handler(self, context):
        """Call the current event loop's exception handler.

        The context argument is a dict containing the following keys:

        - 'message': Error message;
        - 'exception' (optional): Exception object;
        - 'future' (optional): Future instance;
        - 'task' (optional): Task instance;
        - 'handle' (optional): Handle instance;
        - 'protocol' (optional): Protocol instance;
        - 'transport' (optional): Transport instance;
        - 'socket' (optional): Socket instance;
        - 'asyncgen' (optional): Asynchronous generator that caused
                                 the exception.

        New keys maybe introduced in the future.

        Note: do not overload this method in an event loop subclass.
        For custom exception handling, use the
        `set_exception_handler()` method.
        """
        if self._exception_handler is None:
            try:
                self.default_exception_handler(context)
            except (SystemExit, KeyboardInterrupt):
                raise
            except BaseException:
                # Second protection layer for unexpected errors
                # in the default implementation, as well as for subclassed
                # event loops with overloaded "default_exception_handler".
                logger.error('Exception in default exception handler',
                             exc_info=True)
        else:
            try:
                self._exception_handler(self, context)
            except (SystemExit, KeyboardInterrupt):
                raise
            except BaseException as exc:
                # Exception in the user set custom exception handler.
                try:
                    # Let's try default handler.
                    self.default_exception_handler({
                        'message': 'Unhandled error in exception handler',
                        'exception': exc,
                        'context': context,
                    })
                except (SystemExit, KeyboardInterrupt):
                    raise
                except BaseException:
                    # Guard 'default_exception_handler' in case it is
                    # overloaded.
                    logger.error('Exception in default exception handler '
                                 'while handling an unexpected error '
                                 'in custom exception handler',
                                 exc_info=True)

    def _add_callback(self, handle):
        """Add a Handle to _ready."""
        if not handle._cancelled:
            self._ready.append(handle)

    def _add_callback_signalsafe(self, handle):
        """Like _add_callback() but called from a signal handler."""
        self._add_callback(handle)
        self._write_to_self()

    def _timer_handle_cancelled(self, handle):
        """Notification that a TimerHandle has been cancelled."""
        if handle._scheduled:
            self._timer_cancelled_count += 1

    def _run_once(self):
        """Run one full iteration of the event loop.

        This calls all currently ready callbacks, polls for I/O,
        schedules the resulting callbacks, and finally schedules
        'call_later' callbacks.
        """

        sched_count = len(self._scheduled)
        if (sched_count > _MIN_SCHEDULED_TIMER_HANDLES and
            self._timer_cancelled_count / sched_count >
                _MIN_CANCELLED_TIMER_HANDLES_FRACTION):
            # Remove delayed calls that were cancelled if their number
            # is too high
            new_scheduled = []
            for handle in self._scheduled:
                if handle._cancelled:
                    handle._scheduled = False
                else:
                    new_scheduled.append(handle)

            heapq.heapify(new_scheduled)
            self._scheduled = new_scheduled
            self._timer_cancelled_count = 0
        else:
            # Remove delayed calls that were cancelled from head of queue.
            while self._scheduled and self._scheduled[0]._cancelled:
                self._timer_cancelled_count -= 1
                handle = heapq.heappop(self._scheduled)
                handle._scheduled = False

        timeout = None
        if self._ready or self._stopping:
            timeout = 0
        elif self._scheduled:
            # Compute the desired timeout.
            when = self._scheduled[0]._when
            timeout = min(max(0, when - self.time()), MAXIMUM_SELECT_TIMEOUT)

        event_list = self._selector.select(timeout)
        self._process_events(event_list)
        # Needed to break cycles when an exception occurs.
        event_list = None

        # Handle 'later' callbacks that are ready.
        end_time = self.time() + self._clock_resolution
        while self._scheduled:
            handle = self._scheduled[0]
            if handle._when >= end_time:
                break
            handle = heapq.heappop(self._scheduled)
            handle._scheduled = False
            self._ready.append(handle)

        # This is the only place where callbacks are actually *called*.
        # All other places just add them to ready.
        # Note: We run all currently scheduled callbacks, but not any
        # callbacks scheduled by callbacks run this time around --
        # they will be run the next time (after another I/O poll).
        # Use an idiom that is thread-safe without using locks.
        ntodo = len(self._ready)
        for i in range(ntodo):
            handle = self._ready.popleft()
            if handle._cancelled:
                continue
            if self._debug:
                try:
                    self._current_handle = handle
                    t0 = self.time()
                    handle._run()
                    dt = self.time() - t0
                    if dt >= self.slow_callback_duration:
                        logger.warning('Executing %s took %.3f seconds',
                                       _format_handle(handle), dt)
                finally:
                    self._current_handle = None
            else:
                handle._run()
        handle = None  # Needed to break cycles when an exception occurs.

    def _set_coroutine_origin_tracking(self, enabled):
        if bool(enabled) == bool(self._coroutine_origin_tracking_enabled):
            return

        if enabled:
            self._coroutine_origin_tracking_saved_depth = (
                sys.get_coroutine_origin_tracking_depth())
            sys.set_coroutine_origin_tracking_depth(
                constants.DEBUG_STACK_DEPTH)
        else:
            sys.set_coroutine_origin_tracking_depth(
                self._coroutine_origin_tracking_saved_depth)

        self._coroutine_origin_tracking_enabled = enabled

    def get_debug(self):
        return self._debug

    def set_debug(self, enabled):
        self._debug = enabled

        if self.is_running():
            self.call_soon_threadsafe(self._set_coroutine_origin_tracking, enabled)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      """
Module difflib -- helpers for computing deltas between objects.

Function get_close_matches(word, possibilities, n=3, cutoff=0.6):
    Use SequenceMatcher to return list of the best "good enough" matches.

Function context_diff(a, b):
    For two lists of strings, return a delta in context diff format.

Function ndiff(a, b):
    Return a delta: the difference between `a` and `b` (lists of strings).

Function restore(delta, which):
    Return one of the two sequences that generated an ndiff delta.

Function unified_diff(a, b):
    For two lists of strings, return a delta in unified diff format.

Class SequenceMatcher:
    A flexible class for comparing pairs of sequences of any type.

Class Differ:
    For producing human-readable deltas from sequences of lines of text.

Class HtmlDiff:
    For producing HTML side by side comparison with change highlights.
"""

__all__ = ['get_close_matches', 'ndiff', 'restore', 'SequenceMatcher',
           'Differ','IS_CHARACTER_JUNK', 'IS_LINE_JUNK', 'context_diff',
           'unified_diff', 'diff_bytes', 'HtmlDiff', 'Match']

from heapq import nlargest as _nlargest
from collections import namedtuple as _namedtuple
from types import GenericAlias

Match = _namedtuple('Match', 'a b size')

def _calculate_ratio(matches, length):
    if length:
        return 2.0 * matches / length
    return 1.0

class SequenceMatcher:

    """
    SequenceMatcher is a flexible class for comparing pairs of sequences of
    any type, so long as the sequence elements are hashable.  The basic
    algorithm predates, and is a little fancier than, an algorithm
    published in the late 1980's by Ratcliff and Obershelp under the
    hyperbolic name "gestalt pattern matching".  The basic idea is to find
    the longest contiguous matching subsequence that contains no "junk"
    elements (R-O doesn't address junk).  The same idea is then applied
    recursively to the pieces of the sequences to the left and to the right
    of the matching subsequence.  This does not yield minimal edit
    sequences, but does tend to yield matches that "look right" to people.

    SequenceMatcher tries to compute a "human-friendly diff" between two
    sequences.  Unlike e.g. UNIX(tm) diff, the fundamental notion is the
    longest *contiguous* & junk-free matching subsequence.  That's what
    catches peoples' eyes.  The Windows(tm) windiff has another interesting
    notion, pairing up elements that appear uniquely in each sequence.
    That, and the method here, appear to yield more intuitive difference
    reports than does diff.  This method appears to be the least vulnerable
    to syncing up on blocks of "junk lines", though (like blank lines in
    ordinary text files, or maybe "<P>" lines in HTML files).  That may be
    because this is the only method of the 3 that has a *concept* of
    "junk" <wink>.

    Example, comparing two strings, and considering blanks to be "junk":

    >>> s = SequenceMatcher(lambda x: x == " ",
    ...                     "private Thread currentThread;",
    ...                     "private volatile Thread currentThread;")
    >>>

    .ratio() returns a float in [0, 1], measuring the "similarity" of the
    sequences.  As a rule of thumb, a .ratio() value over 0.6 means the
    sequences are close matches:

    >>> print(round(s.ratio(), 3))
    0.866
    >>>

    If you're only interested in where the sequences match,
    .get_matching_blocks() is handy:

    >>> for block in s.get_matching_blocks():
    ...     print("a[%d] and b[%d] match for %d elements" % block)
    a[0] and b[0] match for 8 elements
    a[8] and b[17] match for 21 elements
    a[29] and b[38] match for 0 elements

    Note that the last tuple returned by .get_matching_blocks() is always a
    dummy, (len(a), len(b), 0), and this is the only case in which the last
    tuple element (number of elements matched) is 0.

    If you want to know how to change the first sequence into the second,
    use .get_opcodes():

    >>> for opcode in s.get_opcodes():
    ...     print("%6s a[%d:%d] b[%d:%d]" % opcode)
     equal a[0:8] b[0:8]
    insert a[8:8] b[8:17]
     equal a[8:29] b[17:38]

    See the Differ class for a fancy human-friendly file differencer, which
    uses SequenceMatcher both to compare sequences of lines, and to compare
    sequences of characters within similar (near-matching) lines.

    See also function get_close_matches() in this module, which shows how
    simple code building on SequenceMatcher can be used to do useful work.

    Timing:  Basic R-O is cubic time worst case and quadratic time expected
    case.  SequenceMatcher is quadratic time for the worst case and has
    expected-case behavior dependent in a complicated way on how many
    elements the sequences have in common; best case time is linear.
    """

    def __init__(self, isjunk=None, a='', b='', autojunk=True):
        """Construct a SequenceMatcher.

        Optional arg isjunk is None (the default), or a one-argument
        function that takes a sequence element and returns true iff the
        element is junk.  None is equivalent to passing "lambda x: 0", i.e.
        no elements are considered to be junk.  For example, pass
            lambda x: x in " \\t"
        if you're comparing lines as sequences of characters, and don't
        want to synch up on blanks or hard tabs.

        Optional arg a is the first of two sequences to be compared.  By
        default, an empty string.  The elements of a must be hashable.  See
        also .set_seqs() and .set_seq1().

        Optional arg b is the second of two sequences to be compared.  By
        default, an empty string.  The elements of b must be hashable. See
        also .set_seqs() and .set_seq2().

        Optional arg autojunk should be set to False to disable the
        "automatic junk heuristic" that treats popular elements as junk
        (see module documentation for more information).
        """

        # Members:
        # a
        #      first sequence
        # b
        #      second sequence; differences are computed as "what do
        #      we need to do to 'a' to change it into 'b'?"
        # b2j
        #      for x in b, b2j[x] is a list of the indices (into b)
        #      at which x appears; junk and popular elements do not appear
        # fullbcount
        #      for x in b, fullbcount[x] == the number of times x
        #      appears in b; only materialized if really needed (used
        #      only for computing quick_ratio())
        # matching_blocks
        #      a list of (i, j, k) triples, where a[i:i+k] == b[j:j+k];
        #      ascending & non-overlapping in i and in j; terminated by
        #      a dummy (len(a), len(b), 0) sentinel
        # opcodes
        #      a list of (tag, i1, i2, j1, j2) tuples, where tag is
        #      one of
        #          'replace'   a[i1:i2] should be replaced by b[j1:j2]
        #          'delete'    a[i1:i2] should be deleted
        #          'insert'    b[j1:j2] should be inserted
        #          'equal'     a[i1:i2] == b[j1:j2]
        # isjunk
        #      a user-supplied function taking a sequence element and
        #      returning true iff the element is "junk" -- this has
        #      subtle but helpful effects on the algorithm, which I'll
        #      get around to writing up someday <0.9 wink>.
        #      DON'T USE!  Only __chain_b uses this.  Use "in self.bjunk".
        # bjunk
        #      the items in b for which isjunk is True.
        # bpopular
        #      nonjunk items in b treated as junk by the heuristic (if used).

        self.isjunk = isjunk
        self.a = self.b = None
        self.autojunk = autojunk
        self.set_seqs(a, b)

    def set_seqs(self, a, b):
        """Set the two sequences to be compared.

        >>> s = SequenceMatcher()
        >>> s.set_seqs("abcd", "bcde")
        >>> s.ratio()
        0.75
        """

        self.set_seq1(a)
        self.set_seq2(b)

    def set_seq1(self, a):
        """Set the first sequence to be compared.

        The second sequence to be compared is not changed.

        >>> s = SequenceMatcher(None, "abcd", "bcde")
        >>> s.ratio()
        0.75
        >>> s.set_seq1("bcde")
        >>> s.ratio()
        1.0
        >>>

        SequenceMatcher computes and caches detailed information about the
        second sequence, so if you want to compare one sequence S against
        many sequences, use .set_seq2(S) once and call .set_seq1(x)
        repeatedly for each of the other sequences.

        See also set_seqs() and set_seq2().
        """

        if a is self.a:
            return
        self.a = a
        self.matching_blocks = self.opcodes = None

    def set_seq2(self, b):
        """Set the second sequence to be compared.

        The first sequence to be compared is not changed.

        >>> s = SequenceMatcher(None, "abcd", "bcde")
        >>> s.ratio()
        0.75
        >>> s.set_seq2("abcd")
        >>> s.ratio()
        1.0
        >>>

        SequenceMatcher computes and caches detailed information about the
        second sequence, so if you want to compare one sequence S against
        many sequences, use .set_seq2(S) once and call .set_seq1(x)
        repeatedly for each of the other sequences.

        See also set_seqs() and set_seq1().
        """

        if b is self.b:
            return
        self.b = b
        self.matching_blocks = self.opcodes = None
        self.fullbcount = None
        self.__chain_b()

    # For each element x in b, set b2j[x] to a list of the indices in
    # b where x appears; the indices are in increasing order; note that
    # the number of times x appears in b is len(b2j[x]) ...
    # when self.isjunk is defined, junk elements don't show up in this
    # map at all, which stops the central find_longest_match method
    # from starting any matching block at a junk element ...
    # b2j also does not contain entries for "popular" elements, meaning
    # elements that account for more than 1 + 1% of the total elements, and
    # when the sequence is reasonably large (>= 200 elements); this can
    # be viewed as an adaptive notion of semi-junk, and yields an enormous
    # speedup when, e.g., comparing program files with hundreds of
    # instances of "return NULL;" ...
    # note that this is only called when b changes; so for cross-product
    # kinds of matches, it's best to call set_seq2 once, then set_seq1
    # repeatedly

    def __chain_b(self):
        # Because isjunk is a user-defined (not C) function, and we test
        # for junk a LOT, it's important to minimize the number of calls.
        # Before the tricks described here, __chain_b was by far the most
        # time-consuming routine in the whole module!  If anyone sees
        # Jim Roskind, thank him again for profile.py -- I never would
        # have guessed that.
        # The first trick is to build b2j ignoring the possibility
        # of junk.  I.e., we don't call isjunk at all yet.  Throwing
        # out the junk later is much cheaper than building b2j "right"
        # from the start.
        b = self.b
        self.b2j = b2j = {}

        for i, elt in enumerate(b):
            indices = b2j.setdefault(elt, [])
            indices.append(i)

        # Purge junk elements
        self.bjunk = junk = set()
        isjunk = self.isjunk
        if isjunk:
            for elt in b2j.keys():
                if isjunk(elt):
                    junk.add(elt)
            for elt in junk: # separate loop avoids separate list of keys
                del b2j[elt]

        # Purge popular elements that are not junk
        self.bpopular = popular = set()
        n = len(b)
        if self.autojunk and n >= 200:
            ntest = n // 100 + 1
            for elt, idxs in b2j.items():
                if len(idxs) > ntest:
                    popular.add(elt)
            for elt in popular: # ditto; as fast for 1% deletion
                del b2j[elt]

    def find_longest_match(self, alo=0, ahi=None, blo=0, bhi=None):
        """Find longest matching block in a[alo:ahi] and b[blo:bhi].

        By default it will find the longest match in the entirety of a and b.

        If isjunk is not defined:

        Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where
            alo <= i <= i+k <= ahi
            blo <= j <= j+k <= bhi
        and for all (i',j',k') meeting those conditions,
            k >= k'
            i <= i'
            and if i == i', j <= j'

        In other words, of all maximal matching blocks, return one that
        starts earliest in a, and of all those maximal matching blocks that
        start earliest in a, return the one that starts earliest in b.

        >>> s = SequenceMatcher(None, " abcd", "abcd abcd")
        >>> s.find_longest_match(0, 5, 0, 9)
        Match(a=0, b=4, size=5)

        If isjunk is defined, first the longest matching block is
        determined as above, but with the additional restriction that no
        junk element appears in the block.  Then that block is extended as
        far as possible by matching (only) junk elements on both sides.  So
        the resulting block never matches on junk except as identical junk
        happens to be adjacent to an "interesting" match.

        Here's the same example as before, but considering blanks to be
        junk.  That prevents " abcd" from matching the " abcd" at the tail
        end of the second sequence directly.  Instead only the "abcd" can
        match, and matches the leftmost "abcd" in the second sequence:

        >>> s = SequenceMatcher(lambda x: x==" ", " abcd", "abcd abcd")
        >>> s.find_longest_match(0, 5, 0, 9)
        Match(a=1, b=0, size=4)

        If no blocks match, return (alo, blo, 0).

        >>> s = SequenceMatcher(None, "ab", "c")
        >>> s.find_longest_match(0, 2, 0, 1)
        Match(a=0, b=0, size=0)
        """

        # CAUTION:  stripping common prefix or suffix would be incorrect.
        # E.g.,
        #    ab
        #    acab
        # Longest matching block is "ab", but if common prefix is
        # stripped, it's "a" (tied with "b").  UNIX(tm) diff does so
        # strip, so ends up claiming that ab is changed to acab by
        # inserting "ca" in the middle.  That's minimal but unintuitive:
        # "it's obvious" that someone inserted "ac" at the front.
        # Windiff ends up at the same place as diff, but by pairing up
        # the unique 'b's and then matching the first two 'a's.

        a, b, b2j, isbjunk = self.a, self.b, self.b2j, self.bjunk.__contains__
        if ahi is None:
            ahi = len(a)
        if bhi is None:
            bhi = len(b)
        besti, bestj, bestsize = alo, blo, 0
        # find longest junk-free match
        # during an iteration of the loop, j2len[j] = length of longest
        # junk-free match ending with a[i-1] and b[j]
        j2len = {}
        nothing = []
        for i in range(alo, ahi):
            # look at all instances of a[i] in b; note that because
            # b2j has no junk keys, the loop is skipped if a[i] is junk
            j2lenget = j2len.get
            newj2len = {}
            for j in b2j.get(a[i], nothing):
                # a[i] matches b[j]
                if j < blo:
                    continue
                if j >= bhi:
                    break
                k = newj2len[j] = j2lenget(j-1, 0) + 1
                if k > bestsize:
                    besti, bestj, bestsize = i-k+1, j-k+1, k
            j2len = newj2len

        # Extend the best by non-junk elements on each end.  In particular,
        # "popular" non-junk elements aren't in b2j, which greatly speeds
        # the inner loop above, but also means "the best" match so far
        # doesn't contain any junk *or* popular non-junk elements.
        while besti > alo and bestj > blo and \
              not isbjunk(b[bestj-1]) and \
              a[besti-1] == b[bestj-1]:
            besti, bestj, bestsize = besti-1, bestj-1, bestsize+1
        while besti+bestsize < ahi and bestj+bestsize < bhi and \
              not isbjunk(b[bestj+bestsize]) and \
              a[besti+bestsize] == b[bestj+bestsize]:
            bestsize += 1

        # Now that we have a wholly interesting match (albeit possibly
        # empty!), we may as well suck up the matching junk on each
        # side of it too.  Can't think of a good reason not to, and it
        # saves post-processing the (possibly considerable) expense of
        # figuring out what to do with it.  In the case of an empty
        # interesting match, this is clearly the right thing to do,
        # because no other kind of match is possible in the regions.
        while besti > alo and bestj > blo and \
              isbjunk(b[bestj-1]) and \
              a[besti-1] == b[bestj-1]:
            besti, bestj, bestsize = besti-1, bestj-1, bestsize+1
        while besti+bestsize < ahi and bestj+bestsize < bhi and \
              isbjunk(b[bestj+bestsize]) and \
              a[besti+bestsize] == b[bestj+bestsize]:
            bestsize = bestsize + 1

        return Match(besti, bestj, bestsize)

    def get_matching_blocks(self):
        """Return list of triples describing matching subsequences.

        Each triple is of the form (i, j, n), and means that
        a[i:i+n] == b[j:j+n].  The triples are monotonically increasing in
        i and in j.  New in Python 2.5, it's also guaranteed that if
        (i, j, n) and (i', j', n') are adjacent triples in the list, and
        the second is not the last triple in the list, then i+n != i' or
        j+n != j'.  IOW, adjacent triples never describe adjacent equal
        blocks.

        The last triple is a dummy, (len(a), len(b), 0), and is the only
        triple with n==0.

        >>> s = SequenceMatcher(None, "abxcd", "abcd")
        >>> list(s.get_matching_blocks())
        [Match(a=0, b=0, size=2), Match(a=3, b=2, size=2), Match(a=5, b=4, size=0)]
        """

        if self.matching_blocks is not None:
            return self.matching_blocks
        la, lb = len(self.a), len(self.b)

        # This is most naturally expressed as a recursive algorithm, but
        # at least one user bumped into extreme use cases that exceeded
        # the recursion limit on their box.  So, now we maintain a list
        # ('queue`) of blocks we still need to look at, and append partial
        # results to `matching_blocks` in a loop; the matches are sorted
        # at the end.
        queue = [(0, la, 0, lb)]
        matching_blocks = []
        while queue:
            alo, ahi, blo, bhi = queue.pop()
            i, j, k = x = self.find_longest_match(alo, ahi, blo, bhi)
            # a[alo:i] vs b[blo:j] unknown
            # a[i:i+k] same as b[j:j+k]
            # a[i+k:ahi] vs b[j+k:bhi] unknown
            if k:   # if k is 0, there was no matching block
                matching_blocks.append(x)
                if alo < i and blo < j:
                    queue.append((alo, i, blo, j))
                if i+k < ahi and j+k < bhi:
                    queue.append((i+k, ahi, j+k, bhi))
        matching_blocks.sort()

        # It's possible that we have adjacent equal blocks in the
        # matching_blocks list now.  Starting with 2.5, this code was added
        # to collapse them.
        i1 = j1 = k1 = 0
        non_adjacent = []
        for i2, j2, k2 in matching_blocks:
            # Is this block adjacent to i1, j1, k1?
            if i1 + k1 == i2 and j1 + k1 == j2:
                # Yes, so collapse them -- this just increases the length of
                # the first block by the length of the second, and the first
                # block so lengthened remains the block to compare against.
                k1 += k2
            else:
                # Not adjacent.  Remember the first block (k1==0 means it's
                # the dummy we started with), and make the second block the
                # new block to compare against.
                if k1:
                    non_adjacent.append((i1, j1, k1))
                i1, j1, k1 = i2, j2, k2
        if k1:
            non_adjacent.append((i1, j1, k1))

        non_adjacent.append( (la, lb, 0) )
        self.matching_blocks = list(map(Match._make, non_adjacent))
        return self.matching_blocks

    def get_opcodes(self):
        """Return list of 5-tuples describing how to turn a into b.

        Each tuple is of the form (tag, i1, i2, j1, j2).  The first tuple
        has i1 == j1 == 0, and remaining tuples have i1 == the i2 from the
        tuple preceding it, and likewise for j1 == the previous j2.

        The tags are strings, with these meanings:

        'replace':  a[i1:i2] should be replaced by b[j1:j2]
        'delete':   a[i1:i2] should be deleted.
                    Note that j1==j2 in this case.
        'insert':   b[j1:j2] should be inserted at a[i1:i1].
                    Note that i1==i2 in this case.
        'equal':    a[i1:i2] == b[j1:j2]

        >>> a = "qabxcd"
        >>> b = "abycdf"
        >>> s = SequenceMatcher(None, a, b)
        >>> for tag, i1, i2, j1, j2 in s.get_opcodes():
        ...    print(("%7s a[%d:%d] (%s) b[%d:%d] (%s)" %
        ...           (tag, i1, i2, a[i1:i2], j1, j2, b[j1:j2])))
         delete a[0:1] (q) b[0:0] ()
          equal a[1:3] (ab) b[0:2] (ab)
        replace a[3:4] (x) b[2:3] (y)
          equal a[4:6] (cd) b[3:5] (cd)
         insert a[6:6] () b[5:6] (f)
        """

        if self.opcodes is not None:
            return self.opcodes
        i = j = 0
        self.opcodes = answer = []
        for ai, bj, size in self.get_matching_blocks():
            # invariant:  we've pumped out correct diffs to change
            # a[:i] into b[:j], and the next matching block is
            # a[ai:ai+size] == b[bj:bj+size].  So we need to pump
            # out a diff to change a[i:ai] into b[j:bj], pump out
            # the matching block, and move (i,j) beyond the match
            tag = ''
            if i < ai and j < bj:
                tag = 'replace'
            elif i < ai:
                tag = 'delete'
            elif j < bj:
                tag = 'insert'
            if tag:
                answer.append( (tag, i, ai, j, bj) )
            i, j = ai+size, bj+size
            # the list of matching blocks is terminated by a
            # sentinel with size 0
            if size:
                answer.append( ('equal', ai, i, bj, j) )
        return answer

    def get_grouped_opcodes(self, n=3):
        """ Isolate change clusters by eliminating ranges with no changes.

        Return a generator of groups with up to n lines of context.
        Each group is in the same format as returned by get_opcodes().

        >>> from pprint import pprint
        >>> a = list(map(str, range(1,40)))
        >>> b = a[:]
        >>> b[8:8] = ['i']     # Make an insertion
        >>> b[20] += 'x'       # Make a replacement
        >>> b[23:28] = []      # Make a deletion
        >>> b[30] += 'y'       # Make another replacement
        >>> pprint(list(SequenceMatcher(None,a,b).get_grouped_opcodes()))
        [[('equal', 5, 8, 5, 8), ('insert', 8, 8, 8, 9), ('equal', 8, 11, 9, 12)],
         [('equal', 16, 19, 17, 20),
          ('replace', 19, 20, 20, 21),
          ('equal', 20, 22, 21, 23),
          ('delete', 22, 27, 23, 23),
          ('equal', 27, 30, 23, 26)],
         [('equal', 31, 34, 27, 30),
          ('replace', 34, 35, 30, 31),
          ('equal', 35, 38, 31, 34)]]
        """

        codes = self.get_opcodes()
        if not codes:
            codes = [("equal", 0, 1, 0, 1)]
        # Fixup leading and trailing groups if they show no changes.
        if codes[0][0] == 'equal':
            tag, i1, i2, j1, j2 = codes[0]
            codes[0] = tag, max(i1, i2-n), i2, max(j1, j2-n), j2
        if codes[-1][0] == 'equal':
            tag, i1, i2, j1, j2 = codes[-1]
            codes[-1] = tag, i1, min(i2, i1+n), j1, min(j2, j1+n)

        nn = n + n
        group = []
        for tag, i1, i2, j1, j2 in codes:
            # End the current group and start a new one whenever
            # there is a large range with no changes.
            if tag == 'equal' and i2-i1 > nn:
                group.append((tag, i1, min(i2, i1+n), j1, min(j2, j1+n)))
                yield group
                group = []
                i1, j1 = max(i1, i2-n), max(j1, j2-n)
            group.append((tag, i1, i2, j1 ,j2))
        if group and not (len(group)==1 and group[0][0] == 'equal'):
            yield group

    def ratio(self):
        """Return a measure of the sequences' similarity (float in [0,1]).

        Where T is the total number of elements in both sequences, and
        M is the number of matches, this is 2.0*M / T.
        Note that this is 1 if the sequences are identical, and 0 if
        they have nothing in common.

        .ratio() is expensive to compute if you haven't already computed
        .get_matching_blocks() or .get_opcodes(), in which case you may
        want to try .quick_ratio() or .real_quick_ratio() first to get an
        upper bound.

        >>> s = SequenceMatcher(None, "abcd", "bcde")
        >>> s.ratio()
        0.75
        >>> s.quick_ratio()
        0.75
        >>> s.real_quick_ratio()
        1.0
        """

        matches = sum(triple[-1] for triple in self.get_matching_blocks())
        return _calculate_ratio(matches, len(self.a) + len(self.b))

    def quick_ratio(self):
        """Return an upper bound on ratio() relatively quickly.

        This isn't defined beyond that it is an upper bound on .ratio(), and
        is faster to compute.
        """

        # viewing a and b as multisets, set matches to the cardinality
        # of their intersection; this counts the number of matches
        # without regard to order, so is clearly an upper bound
        if self.fullbcount is None:
            self.fullbcount = fullbcount = {}
            for elt in self.b:
                fullbcount[elt] = fullbcount.get(elt, 0) + 1
        fullbcount = self.fullbcount
        # avail[x] is the number of times x appears in 'b' less the
        # number of times we've seen it in 'a' so far ... kinda
        avail = {}
        availhas, matches = avail.__contains__, 0
        for elt in self.a:
            if availhas(elt):
                numb = avail[elt]
            else:
                numb = fullbcount.get(elt, 0)
            avail[elt] = numb - 1
            if numb > 0:
                matches = matches + 1
        return _calculate_ratio(matches, len(self.a) + len(self.b))

    def real_quick_ratio(self):
        """Return an upper bound on ratio() very quickly.

        This isn't defined beyond that it is an upper bound on .ratio(), and
        is faster to compute than either .ratio() or .quick_ratio().
        """

        la, lb = len(self.a), len(self.b)
        # can't have more matches than the number of elements in the
        # shorter sequence
        return _calculate_ratio(min(la, lb), la + lb)

    __class_getitem__ = classmethod(GenericAlias)


def get_close_matches(word, possibilities, n=3, cutoff=0.6):
    """Use SequenceMatcher to return list of the best "good enough" matches.

    word is a sequence for which close matches are desired (typically a
    string).

    possibilities is a list of sequences against which to match word
    (typically a list of strings).

    Optional arg n (default 3) is the maximum number of close matches to
    return.  n must be > 0.

    Optional arg cutoff (default 0.6) is a float in [0, 1].  Possibilities
    that don't score at least that similar to word are ignored.

    The best (no more than n) matches among the possibilities are returned
    in a list, sorted by similarity score, most similar first.

    >>> get_close_matches("appel", ["ape", "apple", "peach", "puppy"])
    ['apple', 'ape']
    >>> import keyword as _keyword
    >>> get_close_matches("wheel", _keyword.kwlist)
    ['while']
    >>> get_close_matches("Apple", _keyword.kwlist)
    []
    >>> get_close_matches("accept", _keyword.kwlist)
    ['except']
    """

    if not n >  0:
        raise ValueError("n must be > 0: %r" % (n,))
    if not 0.0 <= cutoff <= 1.0:
        raise ValueError("cutoff must be in [0.0, 1.0]: %r" % (cutoff,))
    result = []
    s = SequenceMatcher()
    s.set_seq2(word)
    for x in possibilities:
        s.set_seq1(x)
        if s.real_quick_ratio() >= cutoff and \
           s.quick_ratio() >= cutoff and \
           s.ratio() >= cutoff:
            result.append((s.ratio(), x))

    # Move the best scorers to head of list
    result = _nlargest(n, result)
    # Strip scores for the best n matches
    return [x for score, x in result]


def _keep_original_ws(s, tag_s):
    """Replace whitespace with the original whitespace characters in `s`"""
    return ''.join(
        c if tag_c == " " and c.isspace() else tag_c
        for c, tag_c in zip(s, tag_s)
    )



class Differ:
    r"""
    Differ is a class for comparing sequences of lines of text, and
    producing human-readable differences or deltas.  Differ uses
    SequenceMatcher both to compare sequences of lines, and to compare
    sequences of characters within similar (near-matching) lines.

    Each line of a Differ delta begins with a two-letter code:

        '- '    line unique to sequence 1
        '+ '    line unique to sequence 2
        '  '    line common to both sequences
        '? '    line not present in either input sequence

    Lines beginning with '? ' attempt to guide the eye to intraline
    differences, and were not present in either input sequence.  These lines
    can be confusing if the sequences contain tab characters.

    Note that Differ makes no claim to produce a *minimal* diff.  To the
    contrary, minimal diffs are often counter-intuitive, because they synch
    up anywhere possible, sometimes accidental matches 100 pages apart.
    Restricting synch points to contiguous matches preserves some notion of
    locality, at the occasional cost of producing a longer diff.

    Example: Comparing two texts.

    First we set up the texts, sequences of individual single-line strings
    ending with newlines (such sequences can also be obtained from the
    `readlines()` method of file-like objects):

    >>> text1 = '''  1. Beautiful is better than ugly.
    ...   2. Explicit is better than implicit.
    ...   3. Simple is better than complex.
    ...   4. Complex is better than complicated.
    ... '''.splitlines(keepends=True)
    >>> len(text1)
    4
    >>> text1[0][-1]
    '\n'
    >>> text2 = '''  1. Beautiful is better than ugly.
    ...   3.   Simple is better than complex.
    ...   4. Complicated is better than complex.
    ...   5. Flat is better than nested.
    ... '''.splitlines(keepends=True)

    Next we instantiate a Differ object:

    >>> d = Differ()

    Note that when instantiating a Differ object we may pass functions to
    filter out line and character 'junk'.  See Differ.__init__ for details.

    Finally, we compare the two:

    >>> result = list(d.compare(text1, text2))

    'result' is a list of strings, so let's pretty-print it:

    >>> from pprint import pprint as _pprint
    >>> _pprint(result)
    ['    1. Beautiful is better than ugly.\n',
     '-   2. Explicit is better than implicit.\n',
     '-   3. Simple is better than complex.\n',
     '+   3.   Simple is better than complex.\n',
     '?     ++\n',
     '-   4. Complex is better than complicated.\n',
     '?            ^                     ---- ^\n',
     '+   4. Complicated is better than complex.\n',
     '?           ++++ ^                      ^\n',
     '+   5. Flat is better than nested.\n']

    As a single multi-line string it looks like this:

    >>> print(''.join(result), end="")
        1. Beautiful is better than ugly.
    -   2. Explicit is better than implicit.
    -   3. Simple is better than complex.
    +   3.   Simple is better than complex.
    ?     ++
    -   4. Complex is better than complicated.
    ?            ^                     ---- ^
    +   4. Complicated is better than complex.
    ?           ++++ ^                      ^
    +   5. Flat is better than nested.
    """

    def __init__(self, linejunk=None, charjunk=None):
        """
        Construct a text differencer, with optional filters.

        The two optional keyword parameters are for filter functions:

        - `linejunk`: A function that should accept a single string argument,
          and return true iff the string is junk. The module-level function
          `IS_LINE_JUNK` may be used to filter out lines without visible
          characters, except for at most one splat ('#').  It is recommended
          to leave linejunk None; the underlying SequenceMatcher class has
          an adaptive notion of "noise" lines that's better than any static
          definition the author has ever been able to craft.

        - `charjunk`: A function that should accept a string of length 1. The
          module-level function `IS_CHARACTER_JUNK` may be used to filter out
          whitespace characters (a blank or tab; **note**: bad idea to include
          newline in this!).  Use of IS_CHARACTER_JUNK is recommended.
        """

        self.linejunk = linejunk
        self.charjunk = charjunk

    def compare(self, a, b):
        r"""
        Compare two sequences of lines; generate the resulting delta.

        Each sequence must contain individual single-line strings ending with
        newlines. Such sequences can be obtained from the `readlines()` method
        of file-like objects.  The delta generated also consists of newline-
        terminated strings, ready to be printed as-is via the writelines()
        method of a file-like object.

        Example:

        >>> print(''.join(Differ().compare('one\ntwo\nthree\n'.splitlines(True),
        ...                                'ore\ntree\nemu\n'.splitlines(True))),
        ...       end="")
        - one
        ?  ^
        + ore
        ?  ^
        - two
        - three
        ?  -
        + tree
        + emu
        """

        cruncher = SequenceMatcher(self.linejunk, a, b)
        for tag, alo, ahi, blo, bhi in cruncher.get_opcodes():
            if tag == 'replace':
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            elif tag == 'delete':
                g = self._dump('-', a, alo, ahi)
            elif tag == 'insert':
                g = self._dump('+', b, blo, bhi)
            elif tag == 'equal':
                g = self._dump(' ', a, alo, ahi)
            else:
                raise ValueError('unknown tag %r' % (tag,))

            yield from g

    def _dump(self, tag, x, lo, hi):
        """Generate comparison results for a same-tagged range."""
        for i in range(lo, hi):
            yield '%s %s' % (tag, x[i])

    def _plain_replace(self, a, alo, ahi, b, blo, bhi):
        assert alo < ahi and blo < bhi
        # dump the shorter block first -- reduces the burden on short-term
        # memory if the blocks are of very different sizes
        if bhi - blo < ahi - alo:
            first  = self._dump('+', b, blo, bhi)
            second = self._dump('-', a, alo, ahi)
        else:
            first  = self._dump('-', a, alo, ahi)
            second = self._dump('+', b, blo, bhi)

        for g in first, second:
            yield from g

    def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
        r"""
        When replacing one block of lines with another, search the blocks
        for *similar* lines; the best-matching pair (if any) is used as a
        synch point, and intraline difference marking is done on the
        similar pair. Lots of work, but often worth it.

        Example:

        >>> d = Differ()
        >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
        ...                            ['abcdefGhijkl\n'], 0, 1)
        >>> print(''.join(results), end="")
        - abcDefghiJkl
        ?    ^  ^  ^
        + abcdefGhijkl
        ?    ^  ^  ^
        """

        # don't synch up unless the lines have a similarity score of at
        # least cutoff; best_ratio tracks the best score seen so far
        best_ratio, cutoff = 0.74, 0.75
        cruncher = SequenceMatcher(self.charjunk)
        eqi, eqj = None, None   # 1st indices of equal lines (if any)

        # search for the pair that matches best without being identical
        # (identical lines must be junk lines, & we don't want to synch up
        # on junk -- unless we have to)
        for j in range(blo, bhi):
            bj = b[j]
            cruncher.set_seq2(bj)
            for i in range(alo, ahi):
                ai = a[i]
                if ai == bj:
                    if eqi is None:
                        eqi, eqj = i, j
                    continue
                cruncher.set_seq1(ai)
                # computing similarity is expensive, so use the quick
                # upper bounds first -- have seen this speed up messy
                # compares by a factor of 3.
                # note that ratio() is only expensive to compute the first
                # time it's called on a sequence pair; the expensive part
                # of the computation is cached by cruncher
                if cruncher.real_quick_ratio() > best_ratio and \
                      cruncher.quick_ratio() > best_ratio and \
                      cruncher.ratio() > best_ratio:
                    best_ratio, best_i, best_j = cruncher.ratio(), i, j
        if best_ratio < cutoff:
            # no non-identical "pretty close" pair
            if eqi is None:
                # no identical pair either -- treat it as a straight replace
                yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
                return
            # no close pair, but an identical pair -- synch up on that
            best_i, best_j, best_ratio = eqi, eqj, 1.0
        else:
            # there's a close pair, so forget the identical pair (if any)
            eqi = None

        # a[best_i] very similar to b[best_j]; eqi is None iff they're not
        # identical

        # pump out diffs from before the synch point
        yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)

        # do intraline marking on the synch pair
        aelt, belt = a[best_i], b[best_j]
        if eqi is None:
            # pump out a '-', '?', '+', '?' quad for the synched lines
            atags = btags = ""
            cruncher.set_seqs(aelt, belt)
            for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
                la, lb = ai2 - ai1, bj2 - bj1
                if tag == 'replace':
                    atags += '^' * la
                    btags += '^' * lb
                elif tag == 'delete':
                    atags += '-' * la
                elif tag == 'insert':
                    btags += '+' * lb
                elif tag == 'equal':
                    atags += ' ' * la
                    btags += ' ' * lb
                else:
                    raise ValueError('unknown tag %r' % (tag,))
            yield from self._qformat(aelt, belt, atags, btags)
        else:
            # the synch pair is identical
            yield '  ' + aelt

        # pump out diffs from after the synch point
        yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)

    def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
        g = []
        if alo < ahi:
            if blo < bhi:
                g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
            else:
                g = self._dump('-', a, alo, ahi)
        elif blo < bhi:
            g = self._dump('+', b, blo, bhi)

        yield from g

    def _qformat(self, aline, bline, atags, btags):
        r"""
        Format "?" output and deal with tabs.

        Example:

        >>> d = Differ()
        >>> results = d._qformat('\tabcDefghiJkl\n', '\tabcdefGhijkl\n',
        ...                      '  ^ ^  ^      ', '  ^ ^  ^      ')
        >>> for line in results: print(repr(line))
        ...
        '- \tabcDefghiJkl\n'
        '? \t ^ ^  ^\n'
        '+ \tabcdefGhijkl\n'
        '? \t ^ ^  ^\n'
        """
        atags = _keep_original_ws(aline, atags).rstrip()
        btags = _keep_original_ws(bline, btags).rstrip()

        yield "- " + aline
        if atags:
            yield f"? {atags}\n"

        yield "+ " + bline
        if btags:
            yield f"? {btags}\n"

# With respect to junk, an earlier version of ndiff simply refused to
# *start* a match with a junk element.  The result was cases like this:
#     before: private Thread currentThread;
#     after:  private volatile Thread currentThread;
# If you consider whitespace to be junk, the longest contiguous match
# not starting with junk is "e Thread currentThread".  So ndiff reported
# that "e volatil" was inserted between the 't' and the 'e' in "private".
# While an accurate view, to people that's absurd.  The current version
# looks for matching blocks that are entirely junk-free, then extends the
# longest one of those as far as possible but only with matching junk.
# So now "currentThread" is matched, then extended to suck up the
# preceding blank; then "private" is matched, and extended to suck up the
# following blank; then "Thread" is matched; and finally ndiff reports
# that "volatile " was inserted before "Thread".  The only quibble
# remaining is that perhaps it was really the case that " volatile"
# was inserted after "private".  I can live with that <wink>.

import re

def IS_LINE_JUNK(line, pat=re.compile(r"\s*(?:#\s*)?$").match):
    r"""
    Return True for ignorable line: iff `line` is blank or contains a single '#'.

    Examples:

    >>> IS_LINE_JUNK('\n')
    True
    >>> IS_LINE_JUNK('  #   \n')
    True
    >>> IS_LINE_JUNK('hello\n')
    False
    """

    return pat(line) is not None

def IS_CHARACTER_JUNK(ch, ws=" \t"):
    r"""
    Return True for ignorable character: iff `ch` is a space or tab.

    Examples:

    >>> IS_CHARACTER_JUNK(' ')
    True
    >>> IS_CHARACTER_JUNK('\t')
    True
    >>> IS_CHARACTER_JUNK('\n')
    False
    >>> IS_CHARACTER_JUNK('x')
    False
    """

    return ch in ws


########################################################################
###  Unified Diff
########################################################################

def _format_range_unified(start, stop):
    'Convert range to the "ed" format'
    # Per the diff spec at http://www.unix.org/single_unix_specification/
    beginning = start + 1     # lines start numbering with one
    length = stop - start
    if length == 1:
        return '{}'.format(beginning)
    if not length:
        beginning -= 1        # empty ranges begin at line just before the range
    return '{},{}'.format(beginning, length)

def unified_diff(a, b, fromfile='', tofile='', fromfiledate='',
                 tofiledate='', n=3, lineterm='\n'):
    r"""
    Compare two sequences of lines; generate the delta as a unified diff.

    Unified diffs are a compact way of showing line changes and a few
    lines of context.  The number of context lines is set by 'n' which
    defaults to three.

    By default, the diff control lines (those with ---, +++, or @@) are
    created with a trailing newline.  This is helpful so that inputs
    created from file.readlines() result in diffs that are suitable for
    file.writelines() since both the inputs and outputs have trailing
    newlines.

    For inputs that do not have trailing newlines, set the lineterm
    argument to "" so that the output will be uniformly newline free.

    The unidiff format normally has a header for filenames and modification
    times.  Any or all of these may be specified using strings for
    'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'.
    The modification times are normally expressed in the ISO 8601 format.

    Example:

    >>> for line in unified_diff('one two three four'.split(),
    ...             'zero one tree four'.split(), 'Original', 'Current',
    ...             '2005-01-26 23:30:50', '2010-04-02 10:20:52',
    ...             lineterm=''):
    ...     print(line)                 # doctest: +NORMALIZE_WHITESPACE
    --- Original        2005-01-26 23:30:50
    +++ Current         2010-04-02 10:20:52
    @@ -1,4 +1,4 @@
    +zero
     one
    -two
    -three
    +tree
     four
    """

    _check_types(a, b, fromfile, tofile, fromfiledate, tofiledate, lineterm)
    started = False
    for group in SequenceMatcher(None,a,b).get_grouped_opcodes(n):
        if not started:
            started = True
            fromdate = '\t{}'.format(fromfiledate) if fromfiledate else ''
            todate = '\t{}'.format(tofiledate) if tofiledate else ''
            yield '--- {}{}{}'.format(fromfile, fromdate, lineterm)
            yield '+++ {}{}{}'.format(tofile, todate, lineterm)

        first, last = group[0], group[-1]
        file1_range = _format_range_unified(first[1], last[2])
        file2_range = _format_range_unified(first[3], last[4])
        yield '@@ -{} +{} @@{}'.format(file1_range, file2_range, lineterm)

        for tag, i1, i2, j1, j2 in group:
            if tag == 'equal':
                for line in a[i1:i2]:
                    yield ' ' + line
                continue
            if tag in {'replace', 'delete'}:
                for line in a[i1:i2]:
                    yield '-' + line
            if tag in {'replace', 'insert'}:
                for line in b[j1:j2]:
                    yield '+' + line


########################################################################
###  Context Diff
########################################################################

def _format_range_context(start, stop):
    'Convert range to the "ed" format'
    # Per the diff spec at http://www.unix.org/single_unix_specification/
    beginning = start + 1     # lines start numbering with one
    length = stop - start
    if not length:
        beginning -= 1        # empty ranges begin at line just before the range
    if length <= 1:
        return '{}'.format(beginning)
    return '{},{}'.format(beginning, beginning + length - 1)

# See http://www.unix.org/single_unix_specification/
def context_diff(a, b, fromfile='', tofile='',
                 fromfiledate='', tofiledate='', n=3, lineterm='\n'):
    r"""
    Compare two sequences of lines; generate the delta as a context diff.

    Context diffs are a compact way of showing line changes and a few
    lines of context.  The number of context lines is set by 'n' which
    defaults to three.

    By default, the diff control lines (those with *** or ---) are
    created with a trailing newline.  This is helpful so that inputs
    created from file.readlines() result in diffs that are suitable for
    file.writelines() since both the inputs and outputs have trailing
    newlines.

    For inputs that do not have trailing newlines, set the lineterm
    argument to "" so that the output will be uniformly newline free.

    The context diff format normally has a header for filenames and
    modification times.  Any or all of these may be specified using
    strings for 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'.
    The modification times are normally expressed in the ISO 8601 format.
    If not specified, the strings default to blanks.

    Example:

    >>> print(''.join(context_diff('one\ntwo\nthree\nfour\n'.splitlines(True),
    ...       'zero\none\ntree\nfour\n'.splitlines(True), 'Original', 'Current')),
    ...       end="")
    *** Original
    --- Current
    ***************
    *** 1,4 ****
      one
    ! two
    ! three
      four
    --- 1,4 ----
    + zero
      one
    ! tree
      four
    """

    _check_types(a, b, fromfile, tofile, fromfiledate, tofiledate, lineterm)
    prefix = dict(insert='+ ', delete='- ', replace='! ', equal='  ')
    started = False
    for group in SequenceMatcher(None,a,b).get_grouped_opcodes(n):
        if not started:
            started = True
            fromdate = '\t{}'.format(fromfiledate) if fromfiledate else ''
            todate = '\t{}'.format(tofiledate) if tofiledate else ''
            yield '*** {}{}{}'.format(fromfile, fromdate, lineterm)
            yield '--- {}{}{}'.format(tofile, todate, lineterm)

        first, last = group[0], group[-1]
        yield '***************' + lineterm

        file1_range = _format_range_context(first[1], last[2])
        yield '*** {} ****{}'.format(file1_range, lineterm)

        if any(tag in {'replace', 'delete'} for tag, _, _, _, _ in group):
            for tag, i1, i2, _, _ in group:
                if tag != 'insert':
                    for line in a[i1:i2]:
                        yield prefix[tag] + line

        file2_range = _format_range_context(first[3], last[4])
        yield '--- {} ----{}'.format(file2_range, lineterm)

        if any(tag in {'replace', 'insert'} for tag, _, _, _, _ in group):
            for tag, _, _, j1, j2 in group:
                if tag != 'delete':
                    for line in b[j1:j2]:
                        yield prefix[tag] + line

def _check_types(a, b, *args):
    # Checking types is weird, but the alternative is garbled output when
    # someone passes mixed bytes and str to {unified,context}_diff(). E.g.
    # without this check, passing filenames as bytes results in output like
    #   --- b'oldfile.txt'
    #   +++ b'newfile.txt'
    # because of how str.format() incorporates bytes objects.
    if a and not isinstance(a[0], str):
        raise TypeError('lines to compare must be str, not %s (%r)' %
                        (type(a[0]).__name__, a[0]))
    if b and not isinstance(b[0], str):
        raise TypeError('lines to compare must be str, not %s (%r)' %
                        (type(b[0]).__name__, b[0]))
    for arg in args:
        if not isinstance(arg, str):
            raise TypeError('all arguments must be str, not: %r' % (arg,))

def diff_bytes(dfunc, a, b, fromfile=b'', tofile=b'',
               fromfiledate=b'', tofiledate=b'', n=3, lineterm=b'\n'):
    r"""
    Compare `a` and `b`, two sequences of lines represented as bytes rather
    than str. This is a wrapper for `dfunc`, which is typically either
    unified_diff() or context_diff(). Inputs are losslessly converted to
    strings so that `dfunc` only has to worry about strings, and encoded
    back to bytes on return. This is necessary to compare files with
    unknown or inconsistent encoding. All other inputs (except `n`) must be
    bytes rather than str.
    """
    def decode(s):
        try:
            return s.decode('ascii', 'surrogateescape')
        except AttributeError as err:
            msg = ('all arguments must be bytes, not %s (%r)' %
                   (type(s).__name__, s))
            raise TypeError(msg) from err
    a = list(map(decode, a))
    b = list(map(decode, b))
    fromfile = decode(fromfile)
    tofile = decode(tofile)
    fromfiledate = decode(fromfiledate)
    tofiledate = decode(tofiledate)
    lineterm = decode(lineterm)

    lines = dfunc(a, b, fromfile, tofile, fromfiledate, tofiledate, n, lineterm)
    for line in lines:
        yield line.encode('ascii', 'surrogateescape')

def ndiff(a, b, linejunk=None, charjunk=IS_CHARACTER_JUNK):
    r"""
    Compare `a` and `b` (lists of strings); return a `Differ`-style delta.

    Optional keyword parameters `linejunk` and `charjunk` are for filter
    functions, or can be None:

    - linejunk: A function that should accept a single string argument and
      return true iff the string is junk.  The default is None, and is
      recommended; the underlying SequenceMatcher class has an adaptive
      notion of "noise" lines.

    - charjunk: A function that accepts a character (string of length
      1), and returns true iff the character is junk. The default is
      the module-level function IS_CHARACTER_JUNK, which filters out
      whitespace characters (a blank or tab; note: it's a bad idea to
      include newline in this!).

    Tools/scripts/ndiff.py is a command-line front-end to this function.

    Example:

    >>> diff = ndiff('one\ntwo\nthree\n'.splitlines(keepends=True),
    ...              'ore\ntree\nemu\n'.splitlines(keepends=True))
    >>> print(''.join(diff), end="")
    - one
    ?  ^
    + ore
    ?  ^
    - two
    - three
    ?  -
    + tree
    + emu
    """
    return Differ(linejunk, charjunk).compare(a, b)

def _mdiff(fromlines, tolines, context=None, linejunk=None,
           charjunk=IS_CHARACTER_JUNK):
    r"""Returns generator yielding marked up from/to side by side differences.

    Arguments:
    fromlines -- list of text lines to compared to tolines
    tolines -- list of text lines to be compared to fromlines
    context -- number of context lines to display on each side of difference,
               if None, all from/to text lines will be generated.
    linejunk -- passed on to ndiff (see ndiff documentation)
    charjunk -- passed on to ndiff (see ndiff documentation)

    This function returns an iterator which returns a tuple:
    (from line tuple, to line tuple, boolean flag)

    from/to line tuple -- (line num, line text)
        line num -- integer or None (to indicate a context separation)
        line text -- original line text with following markers inserted:
            '\0+' -- marks start of added text
            '\0-' -- marks start of deleted text
            '\0^' -- marks start of changed text
            '\1' -- marks end of added/deleted/changed text

    boolean flag -- None indicates context separation, True indicates
        either "from" or "to" line contains a change, otherwise False.

    This function/iterator was originally developed to generate side by side
    file difference for making HTML pages (see HtmlDiff class for example
    usage).

    Note, this function utilizes the ndiff function to generate the side by
    side difference markup.  Optional ndiff arguments may be passed to this
    function and they in turn will be passed to ndiff.
    """
    import re

    # regular expression for finding intraline change indices
    change_re = re.compile(r'(\++|\-+|\^+)')

    # create the difference iterator to generate the differences
    diff_lines_iterator = ndiff(fromlines,tolines,linejunk,charjunk)

    def _make_line(lines, format_key, side, num_lines=[0,0]):
        """Returns line of text with user's change markup and line formatting.

        lines -- list of lines from the ndiff generator to produce a line of
                 text from.  When producing the line of text to return, the
                 lines used are removed from this list.
        format_key -- '+' return first line in list with "add" markup around
                          the entire line.
                      '-' return first line in list with "delete" markup around
                          the entire line.
                      '?' return first line in list with add/delete/change
                          intraline markup (indices obtained from second line)
                      None return first line in list with no markup
        side -- indice into the num_lines list (0=from,1=to)
        num_lines -- from/to current line number.  This is NOT intended to be a
                     passed parameter.  It is present as a keyword argument to
                     maintain memory of the current line numbers between calls
                     of this function.

        Note, this function is purposefully not defined at the module scope so
        that data it needs from its parent function (within whose context it
        is defined) does not need to be of module scope.
        """
        num_lines[side] += 1
        # Handle case where no user markup is to be added, just return line of
        # text with user's line format to allow for usage of the line number.
        if format_key is None:
            return (num_lines[side],lines.pop(0)[2:])
        # Handle case of intraline changes
        if format_key == '?':
            text, markers = lines.pop(0), lines.pop(0)
            # find intraline changes (store change type and indices in tuples)
            sub_info = []
            def record_sub_info(match_object,sub_info=sub_info):
                sub_info.append([match_object.group(1)[0],match_object.span()])
                return match_object.group(1)
            change_re.sub(record_sub_info,markers)
            # process each tuple inserting our special marks that won't be
            # noticed by an xml/html escaper.
            for key,(begin,end) in reversed(sub_info):
                text = text[0:begin]+'\0'+key+text[begin:end]+'\1'+text[end:]
            text = text[2:]
        # Handle case of add/delete entire line
        else:
            text = lines.pop(0)[2:]
            # if line of text is just a newline, insert a space so there is
            # something for the user to highlight and see.
            if not text:
                text = ' '
            # insert marks that won't be noticed by an xml/html escaper.
            text = '\0' + format_key + text + '\1'
        # Return line of text, first allow user's line formatter to do its
        # thing (such as adding the line number) then replace the special
        # marks with what the user's change markup.
        return (num_lines[side],text)

    def _line_iterator():
        """Yields from/to lines of text with a change indication.

        This function is an iterator.  It itself pulls lines from a
        differencing iterator, processes them and yields them.  When it can
        it yields both a "from" and a "to" line, otherwise it will yield one
        or the other.  In addition to yielding the lines of from/to text, a
        boolean flag is yielded to indicate if the text line(s) have
        differences in them.

        Note, this function is purposefully not defined at the module scope so
        that data it needs from its parent function (within whose context it
        is defined) does not need to be of module scope.
        """
        lines = []
        num_blanks_pending, num_blanks_to_yield = 0, 0
        while True:
            # Load up next 4 lines so we can look ahead, create strings which
            # are a concatenation of the first character of each of the 4 lines
            # so we can do some very readable comparisons.
            while len(lines) < 4:
                lines.append(next(diff_lines_iterator, 'X'))
            s = ''.join([line[0] for line in lines])
            if s.startswith('X'):
                # When no more lines, pump out any remaining blank lines so the
                # corresponding add/delete lines get a matching blank line so
                # all line pairs get yielded at the next level.
                num_blanks_to_yield = num_blanks_pending
            elif s.startswith('-?+?'):
                # simple intraline change
                yield _make_line(lines,'?',0), _make_line(lines,'?',1), True
                continue
            elif s.startswith('--++'):
                # in delete block, add block coming: we do NOT want to get
                # caught up on blank lines yet, just process the delete line
                num_blanks_pending -= 1
                yield _make_line(lines,'-',0), None, True
                continue
            elif s.startswith(('--?+', '--+', '- ')):
                # in delete block and see an intraline change or unchanged line
                # coming: yield the delete line and then blanks
                from_line,to_line = _make_line(lines,'-',0), None
                num_blanks_to_yield,num_blanks_pending = num_blanks_pending-1,0
            elif s.startswith('-+?'):
                # intraline change
                yield _make_line(lines,None,0), _make_line(lines,'?',1), True
                continue
            elif s.startswith('-?+'):
                # intraline change
                yield _make_line(lines,'?',0), _make_line(lines,None,1), True
                continue
            elif s.startswith('-'):
                # delete FROM line
                num_blanks_pending -= 1
                yield _make_line(lines,'-',0), None, True
                continue
            elif s.startswith('+--'):
                # in add block, delete block coming: we do NOT want to get
                # caught up on blank lines yet, just process the add line
                num_blanks_pending += 1
                yield None, _make_line(lines,'+',1), True
                continue
            elif s.startswith(('+ ', '+-')):
                # will be leaving an add block: yield blanks then add line
                from_line, to_line = None, _make_line(lines,'+',1)
                num_blanks_to_yield,num_blanks_pending = num_blanks_pending+1,0
            elif s.startswith('+'):
                # inside an add block, yield the add line
                num_blanks_pending += 1
                yield None, _make_line(lines,'+',1), True
                continue
            elif s.startswith(' '):
                # unchanged text, yield it to both sides
                yield _make_line(lines[:],None,0),_make_line(lines,None,1),False
                continue
            # Catch up on the blank lines so when we yield the next from/to
            # pair, they are lined up.
            while(num_blanks_to_yield < 0):
                num_blanks_to_yield += 1
                yield None,('','\n'),True
            while(num_blanks_to_yield > 0):
                num_blanks_to_yield -= 1
                yield ('','\n'),None,True
            if s.startswith('X'):
                return
            else:
                yield from_line,to_line,True

    def _line_pair_iterator():
        """Yields from/to lines of text with a change indication.

        This function is an iterator.  It itself pulls lines from the line
        iterator.  Its difference from that iterator is that this function
        always yields a pair of from/to text lines (with the change
        indication).  If necessary it will collect single from/to lines
        until it has a matching pair from/to pair to yield.

        Note, this function is purposefully not defined at the module scope so
        that data it needs from its parent function (within whose context it
        is defined) does not need to be of module scope.
        """
        line_iterator = _line_iterator()
        fromlines,tolines=[],[]
        while True:
            # Collecting lines of text until we have a from/to pair
            while (len(fromlines)==0 or len(tolines)==0):
                try:
                    from_line, to_line, found_diff = next(line_iterator)
                except StopIteration:
                    return
                if from_line is not None:
                    fromlines.append((from_line,found_diff))
                if to_line is not None:
                    tolines.append((to_line,found_diff))
            # Once we have a pair, remove them from the collection and yield it
            from_line, fromDiff = fromlines.pop(0)
            to_line, to_diff = tolines.pop(0)
            yield (from_line,to_line,fromDiff or to_diff)

    # Handle case where user does not want context differencing, just yield
    # them up without doing anything else with them.
    line_pair_iterator = _line_pair_iterator()
    if context is None:
        yield from line_pair_iterator
    # Handle case where user wants context differencing.  We must do some
    # storage of lines until we know for sure that they are to be yielded.
    else:
        context += 1
        lines_to_write = 0
        while True:
            # Store lines up until we find a difference, note use of a
            # circular queue because we only need to keep around what
            # we need for context.
            index, contextLines = 0, [None]*(context)
            found_diff = False
            while(found_diff is False):
                try:
                    from_line, to_line, found_diff = next(line_pair_iterator)
                except StopIteration:
                    return
                i = index % context
                contextLines[i] = (from_line, to_line, found_diff)
                index += 1
            # Yield lines that we have collected so far, but first yield
            # the user's separator.
            if index > context:
                yield None, None, None
                lines_to_write = context
            else:
                lines_to_write = index
                index = 0
            while(lines_to_write):
                i = index % context
                index += 1
                yield contextLines[i]
                lines_to_write -= 1
            # Now yield the context lines after the change
            lines_to_write = context-1
            try:
                while(lines_to_write):
                    from_line, to_line, found_diff = next(line_pair_iterator)
                    # If another change within the context, extend the context
                    if found_diff:
                        lines_to_write = context-1
                    else:
                        lines_to_write -= 1
                    yield from_line, to_line, found_diff
            except StopIteration:
                # Catch exception from next() and return normally
                return


_file_template = """
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html>

<head>
    <meta http-equiv="Content-Type"
          content="text/html; charset=%(charset)s" />
    <title></title>
    <style type="text/css">%(styles)s
    </style>
</head>

<body>
    %(table)s%(legend)s
</body>

</html>"""

_styles = """
        table.diff {font-family:Courier; border:medium;}
        .diff_header {background-color:#e0e0e0}
        td.diff_header {text-align:right}
        .diff_next {background-color:#c0c0c0}
        .diff_add {background-color:#aaffaa}
        .diff_chg {background-color:#ffff77}
        .diff_sub {background-color:#ffaaaa}"""

_table_template = """
    <table class="diff" id="difflib_chg_%(prefix)s_top"
           cellspacing="0" cellpadding="0" rules="groups" >
        <colgroup></colgroup> <colgroup></colgroup> <colgroup></colgroup>
        <colgroup></colgroup> <colgroup></colgroup> <colgroup></colgroup>
        %(header_row)s
        <tbody>
%(data_rows)s        </tbody>
    </table>"""

_legend = """
    <table class="diff" summary="Legends">
        <tr> <th colspan="2"> Legends </th> </tr>
        <tr> <td> <table border="" summary="Colors">
                      <tr><th> Colors </th> </tr>
                      <tr><td class="diff_add">&nbsp;Added&nbsp;</td></tr>
                      <tr><td class="diff_chg">Changed</td> </tr>
                      <tr><td class="diff_sub">Deleted</td> </tr>
                  </table></td>
             <td> <table border="" summary="Links">
                      <tr><th colspan="2"> Links </th> </tr>
                      <tr><td>(f)irst change</td> </tr>
                      <tr><td>(n)ext change</td> </tr>
                      <tr><td>(t)op</td> </tr>
                  </table></td> </tr>
    </table>"""

class HtmlDiff(object):
    """For producing HTML side by side comparison with change highlights.

    This class can be used to create an HTML table (or a complete HTML file
    containing the table) showing a side by side, line by line comparison
    of text with inter-line and intra-line change highlights.  The table can
    be generated in either full or contextual difference mode.

    The following methods are provided for HTML generation:

    make_table -- generates HTML for a single side by side table
    make_file -- generates complete HTML file with a single side by side table

    See tools/scripts/diff.py for an example usage of this class.
    """

    _file_template = _file_template
    _styles = _styles
    _table_template = _table_template
    _legend = _legend
    _default_prefix = 0

    def __init__(self,tabsize=8,wrapcolumn=None,linejunk=None,
                 charjunk=IS_CHARACTER_JUNK):
        """HtmlDiff instance initializer

        Arguments:
        tabsize -- tab stop spacing, defaults to 8.
        wrapcolumn -- column number where lines are broken and wrapped,
            defaults to None where lines are not wrapped.
        linejunk,charjunk -- keyword arguments passed into ndiff() (used by
            HtmlDiff() to generate the side by side HTML differences).  See
            ndiff() documentation for argument default values and descriptions.
        """
        self._tabsize = tabsize
        self._wrapcolumn = wrapcolumn
        self._linejunk = linejunk
        self._charjunk = charjunk

    def make_file(self, fromlines, tolines, fromdesc='', todesc='',
                  context=False, numlines=5, *, charset='utf-8'):
        """Returns HTML file of side by side comparison with change highlights

        Arguments:
        fromlines -- list of "from" lines
        tolines -- list of "to" lines
        fromdesc -- "from" file column header string
        todesc -- "to" file column header string
        context -- set to True for contextual differences (defaults to False
            which shows full differences).
        numlines -- number of context lines.  When context is set True,
            controls number of lines displayed before and after the change.
            When context is False, controls the number of lines to place
            the "next" link anchors before the next change (so click of
            "next" link jumps to just before the change).
        charset -- charset of the HTML document
        """

        return (self._file_template % dict(
            styles=self._styles,
            legend=self._legend,
            table=self.make_table(fromlines, tolines, fromdesc, todesc,
                                  context=context, numlines=numlines),
            charset=charset
        )).encode(charset, 'xmlcharrefreplace').decode(charset)

    def _tab_newline_replace(self,fromlines,tolines):
        """Returns from/to line lists with tabs expanded and newlines removed.

        Instead of tab characters being replaced by the number of spaces
        needed to fill in to the next tab stop, this function will fill
        the space with tab characters.  This is done so that the difference
        algorithms can identify changes in a file when tabs are replaced by
        spaces and vice versa.  At the end of the HTML generation, the tab
        characters will be replaced with a nonbreakable space.
        """
        def expand_tabs(line):
            # hide real spaces
            line = line.replace(' ','\0')
            # expand tabs into spaces
            line = line.expandtabs(self._tabsize)
            # replace spaces from expanded tabs back into tab characters
            # (we'll replace them with markup after we do differencing)
            line = line.replace(' ','\t')
            return line.replace('\0',' ').rstrip('\n')
        fromlines = [expand_tabs(line) for line in fromlines]
        tolines = [expand_tabs(line) for line in tolines]
        return fromlines,tolines

    def _split_line(self,data_list,line_num,text):
        """Builds list of text lines by splitting text lines at wrap point

        This function will determine if the input text line needs to be
        wrapped (split) into separate lines.  If so, the first wrap point
        will be determined and the first line appended to the output
        text line list.  This function is used recursively to handle
        the second part of the split line to further split it.
        """
        # if blank line or context separator, just add it to the output list
        if not line_num:
            data_list.append((line_num,text))
            return

        # if line text doesn't need wrapping, just add it to the output list
        size = len(text)
        max = self._wrapcolumn
        if (size <= max) or ((size -(text.count('\0')*3)) <= max):
            data_list.append((line_num,text))
            return

        # scan text looking for the wrap point, keeping track if the wrap
        # point is inside markers
        i = 0
        n = 0
        mark = ''
        while n < max and i < size:
            if text[i] == '\0':
                i += 1
                mark = text[i]
                i += 1
            elif text[i] == '\1':
                i += 1
                mark = ''
            else:
                i += 1
                n += 1

        # wrap point is inside text, break it up into separate lines
        line1 = text[:i]
        line2 = text[i:]

        # if wrap point is inside markers, place end marker at end of first
        # line and start marker at beginning of second line because each
        # line will have its own table tag markup around it.
        if mark:
            line1 = line1 + '\1'
            line2 = '\0' + mark + line2

        # tack on first line onto the output list
        data_list.append((line_num,line1))

        # use this routine again to wrap the remaining text
        self._split_line(data_list,'>',line2)

    def _line_wrapper(self,diffs):
        """Returns iterator that splits (wraps) mdiff text lines"""

        # pull from/to data and flags from mdiff iterator
        for fromdata,todata,flag in diffs:
            # check for context separators and pass them through
            if flag is None:
                yield fromdata,todata,flag
                continue
            (fromline,fromtext),(toline,totext) = fromdata,todata
            # for each from/to line split it at the wrap column to form
            # list of text lines.
            fromlist,tolist = [],[]
            self._split_line(fromlist,fromline,fromtext)
            self._split_line(tolist,toline,totext)
            # yield from/to line in pairs inserting blank lines as
            # necessary when one side has more wrapped lines
            while fromlist or tolist:
                if fromlist:
                    fromdata = fromlist.pop(0)
                else:
                    fromdata = ('',' ')
                if tolist:
                    todata = tolist.pop(0)
                else:
                    todata = ('',' ')
                yield fromdata,todata,flag

    def _collect_lines(self,diffs):
        """Collects mdiff output into separate lists

        Before storing the mdiff from/to data into a list, it is converted
        into a single line of text with HTML markup.
        """

        fromlist,tolist,flaglist = [],[],[]
        # pull from/to data and flags from mdiff style iterator
        for fromdata,todata,flag in diffs:
            try:
                # store HTML markup of the lines into the lists
                fromlist.append(self._format_line(0,flag,*fromdata))
                tolist.append(self._format_line(1,flag,*todata))
            except TypeError:
                # exceptions occur for lines where context separators go
                fromlist.append(None)
                tolist.append(None)
            flaglist.append(flag)
        return fromlist,tolist,flaglist

    def _format_line(self,side,flag,linenum,text):
        """Returns HTML markup of "from" / "to" text lines

        side -- 0 or 1 indicating "from" or "to" text
        flag -- indicates if difference on line
        linenum -- line number (used for line number column)
        text -- line text to be marked up
        """
        try:
            linenum = '%d' % linenum
            id = ' id="%s%s"' % (self._prefix[side],linenum)
        except TypeError:
            # handle blank lines where linenum is '>' or ''
            id = ''
        # replace those things that would get confused with HTML symbols
        text=text.replace("&","&amp;").replace(">","&gt;").replace("<","&lt;")

        # make space non-breakable so they don't get compressed or line wrapped
        text = text.replace(' ','&nbsp;').rstrip()

        return '<td class="diff_header"%s>%s</td><td nowrap="nowrap">%s</td>' \
               % (id,linenum,text)

    def _make_prefix(self):
        """Create unique anchor prefixes"""

        # Generate a unique anchor prefix so multiple tables
        # can exist on the same HTML page without conflicts.
        fromprefix = "from%d_" % HtmlDiff._default_prefix
        toprefix = "to%d_" % HtmlDiff._default_prefix
        HtmlDiff._default_prefix += 1
        # store prefixes so line format method has access
        self._prefix = [fromprefix,toprefix]

    def _convert_flags(self,fromlist,tolist,flaglist,context,numlines):
        """Makes list of "next" links"""

        # all anchor names will be generated using the unique "to" prefix
        toprefix = self._prefix[1]

        # process change flags, generating middle column of next anchors/links
        next_id = ['']*len(flaglist)
        next_href = ['']*len(flaglist)
        num_chg, in_change = 0, False
        last = 0
        for i,flag in enumerate(flaglist):
            if flag:
                if not in_change:
                    in_change = True
                    last = i
                    # at the beginning of a change, drop an anchor a few lines
                    # (the context lines) before the change for the previous
                    # link
                    i = max([0,i-numlines])
                    next_id[i] = ' id="difflib_chg_%s_%d"' % (toprefix,num_chg)
                    # at the beginning of a change, drop a link to the next
                    # change
                    num_chg += 1
                    next_href[last] = '<a href="#difflib_chg_%s_%d">n</a>' % (
                         toprefix,num_chg)
            else:
                in_change = False
        # check for cases where there is no content to avoid exceptions
        if not flaglist:
            flaglist = [False]
            next_id = ['']
            next_href = ['']
            last = 0
            if context:
                fromlist = ['<td></td><td>&nbsp;No Differences Found&nbsp;</td>']
                tolist = fromlist
            else:
                fromlist = tolist = ['<td></td><td>&nbsp;Empty File&nbsp;</td>']
        # if not a change on first line, drop a link
        if not flaglist[0]:
            next_href[0] = '<a href="#difflib_chg_%s_0">f</a>' % toprefix
        # redo the last link to link to the top
        next_href[last] = '<a href="#difflib_chg_%s_top">t</a>' % (toprefix)

        return fromlist,tolist,flaglist,next_href,next_id

    def make_table(self,fromlines,tolines,fromdesc='',todesc='',context=False,
                   numlines=5):
        """Returns HTML table of side by side comparison with change highlights

        Arguments:
        fromlines -- list of "from" lines
        tolines -- list of "to" lines
        fromdesc -- "from" file column header string
        todesc -- "to" file column header string
        context -- set to True for contextual differences (defaults to False
            which shows full differences).
        numlines -- number of context lines.  When context is set True,
            controls number of lines displayed before and after the change.
            When context is False, controls the number of lines to place
            the "next" link anchors before the next change (so click of
            "next" link jumps to just before the change).
        """

        # make unique anchor prefixes so that multiple tables may exist
        # on the same page without conflict.
        self._make_prefix()

        # change tabs to spaces before it gets more difficult after we insert
        # markup
        fromlines,tolines = self._tab_newline_replace(fromlines,tolines)

        # create diffs iterator which generates side by side from/to data
        if context:
            context_lines = numlines
        else:
            context_lines = None
        diffs = _mdiff(fromlines,tolines,context_lines,linejunk=self._linejunk,
                      charjunk=self._charjunk)

        # set up iterator to wrap lines that exceed desired width
        if self._wrapcolumn:
            diffs = self._line_wrapper(diffs)

        # collect up from/to lines and flags into lists (also format the lines)
        fromlist,tolist,flaglist = self._collect_lines(diffs)

        # process change flags, generating middle column of next anchors/links
        fromlist,tolist,flaglist,next_href,next_id = self._convert_flags(
            fromlist,tolist,flaglist,context,numlines)

        s = []
        fmt = '            <tr><td class="diff_next"%s>%s</td>%s' + \
              '<td class="diff_next">%s</td>%s</tr>\n'
        for i in range(len(flaglist)):
            if flaglist[i] is None:
                # mdiff yields None on separator lines skip the bogus ones
                # generated for the first line
                if i > 0:
                    s.append('        </tbody>        \n        <tbody>\n')
            else:
                s.append( fmt % (next_id[i],next_href[i],fromlist[i],
                                           next_href[i],tolist[i]))
        if fromdesc or todesc:
            header_row = '<thead><tr>%s%s%s%s</tr></thead>' % (
                '<th class="diff_next"><br /></th>',
                '<th colspan="2" class="diff_header">%s</th>' % fromdesc,
                '<th class="diff_next"><br /></th>',
                '<th colspan="2" class="diff_header">%s</th>' % todesc)
        else:
            header_row = ''

        table = self._table_template % dict(
            data_rows=''.join(s),
            header_row=header_row,
            prefix=self._prefix[1])

        return table.replace('\0+','<span class="diff_add">'). \
                     replace('\0-','<span class="diff_sub">'). \
                     replace('\0^','<span class="diff_chg">'). \
                     replace('\1','</span>'). \
                     replace('\t','&nbsp;')

del re

def restore(delta, which):
    r"""
    Generate one of the two sequences that generated a delta.

    Given a `delta` produced by `Differ.compare()` or `ndiff()`, extract
    lines originating from file 1 or 2 (parameter `which`), stripping off line
    prefixes.

    Examples:

    >>> diff = ndiff('one\ntwo\nthree\n'.splitlines(keepends=True),
    ...              'ore\ntree\nemu\n'.splitlines(keepends=True))
    >>> diff = list(diff)
    >>> print(''.join(restore(diff, 1)), end="")
    one
    two
    three
    >>> print(''.join(restore(diff, 2)), end="")
    ore
    tree
    emu
    """
    try:
        tag = {1: "- ", 2: "+ "}[int(which)]
    except KeyError:
        raise ValueError('unknown delta choice (must be 1 or 2): %r'
                           % which) from None
    prefixes = ("  ", tag)
    for line in delta:
        if line[:2] in prefixes:
            yield line[2:]

def _test():
    import doctest, difflib
    return doctest.testmod(difflib)

if __name__ == "__main__":
    _test()
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    