This file is indexed.

/usr/lib/python3/dist-packages/ufl/exprequals.py is in python3-ufl 2017.2.0.0-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# -*- coding: utf-8 -*-

from collections import defaultdict
from six.moves import zip

from ufl.core.expr import Expr
from ufl.log import error

hash_total = defaultdict(int)
hash_collisions = defaultdict(int)
hash_equals = defaultdict(int)
hash_notequals = defaultdict(int)


def print_collisions():

    keys = sorted(hash_total.keys(), key=lambda x: (hash_collisions[x], x))

    print("Collision statistics ({0} keys):".format(len(keys)))
    print("[key: equals; notequals; collisions]")
    n = max(len(str(k)) for k in keys)
    fmt = ("%%%ds" % n) + ": \t %6d (%3d%%); %6d (%3d%%); %6d (%3d%%) col; tot %d"
    for k in keys:
        co = hash_collisions[k]
        eq = hash_equals[k]
        ne = hash_notequals[k]
        tot = hash_total[k]
        sn, on = k
        # Skip those that are all not equal
        if sn != on and ne == tot:
            continue
        print(fmt % (k, eq, int(100.0*eq/tot),
                     ne, int(100.0*ne/tot),
                     co, int(100.0*co/tot),
                     tot))


def measure_collisions(equals_func):
    def equals_func_with_collision_measuring(self, other):
        # Call equals
        equal = equals_func(self, other)

        # Get properties
        st = type(self)
        ot = type(other)
        sn = st.__name__
        on = ot.__name__
        sh = hash(self)
        oh = hash(other)
        key = (sn, on)

        # If hashes are the same but objects are not equal, we have a
        # collision
        hash_total[key] += 1
        if sh == oh and not equal:
            hash_collisions[key] += 1
        elif sh != oh and equal:
            error("Equal objects must always have the same hash! Objects are:\n{0}\n{1}".format(self, other))
        elif sh == oh and equal:
            hash_equals[key] += 1
        elif sh != oh and not equal:
            hash_notequals[key] += 1

        return equal
    return equals_func_with_collision_measuring


# @measure_collisions
def recursive_expr_equals(self, other):  # Much faster than the more complex algorithms above!
    """Checks whether the two expressions are represented the
    exact same way. This does not check if the expressions are
    mathematically equal or equivalent! Used by sets and dicts."""

    # To handle expr == int/float
    if not isinstance(other, Expr):
        return False

    # Fast cutoff for common case
    if self._ufl_typecode_ != other._ufl_typecode_:
        return False

    # Compare hashes, will cutoff more or less all nonequal types
    if hash(self) != hash(other):
        return False

    # Large objects are costly to compare with themselves
    if self is other:
        return True

    # Terminals
    if self._ufl_is_terminal_:
        # Compare terminals with custom == to capture subclass
        # overloading of __eq__
        return self == other

    # --- Operators, most likely equal, below here is the costly part
    # --- if it recurses through a large tree! ---

    # Recurse manually to call expr_equals directly without the class
    # EQ overhead!
    equal = all(recursive_expr_equals(a, b) for (a, b) in zip(self.ufl_operands,
                                                              other.ufl_operands))

    return equal


# @measure_collisions
def nonrecursive_expr_equals(self, other):
    """Checks whether the two expressions are represented the
    exact same way. This does not check if the expressions are
    mathematically equal or equivalent! Used by sets and dicts."""

    # Fast cutoffs for common cases, type difference or hash
    # difference will cutoff more or less all nonequal types
    if type(self) != type(other) or hash(self) != hash(other):
        return False

    # Large objects are costly to compare with themselves
    if self is other:
        return True

    # Modelled after pre_traversal to avoid recursion:
    left = [(self, other)]
    while left:
        s, o = left.pop()

        if s._ufl_is_terminal_:
            # Compare terminals
            if not s == o:
                return False
        else:
            # Delve into subtrees
            so = s.ufl_operands
            oo = o.ufl_operands
            if len(so) != len(oo):
                return False

            for s, o in zip(so, oo):
                # Fast cutoff for common case
                if s._ufl_typecode_ != o._ufl_typecode_:
                    return False
                # Skip subtree if objects are the same
                if s is o:
                    continue
                # Append subtree for further inspection
                left.append((s, o))

    # Equal if we get out of the above loop!
    return True


# expr_equals = recursive_expr_equals
expr_equals = nonrecursive_expr_equals