This file is indexed.

/usr/share/pyshared/ffc/quadrature/symbol.py is in python-ffc 1.0.0-1.

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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
"This file implements a class to represent a symbol."

# Copyright (C) 2009-2011 Kristian B. Oelgaard
#
# This file is part of FFC.
#
# FFC is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# FFC 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with FFC. If not, see <http://www.gnu.org/licenses/>.
#
# First added:  2009-07-12
# Last changed: 2011-06-28

# FFC modules.
from ffc.log import error

# FFC quadrature modules.
from symbolics import type_to_string
from symbolics import create_float
from symbolics import create_product
from symbolics import create_sum
from symbolics import create_fraction
from expr import Expr

class Symbol(Expr):
    __slots__ = ("v", "base_expr", "base_op", "exp", "cond")
    def __init__(self, variable, symbol_type, base_expr=None, base_op=0, expo=None, cond=()):
        """Initialise a Symbols object, it derives from Expr and contains
        the additional variables:

        v         - string, variable name
        base_expr - Other expression type like 'x*y + z'
        base_op   - number of operations for the symbol itself if it's a math
                    operation like std::cos(.) -> base_op = 1.
        NOTE: self._prec = 1."""

        # Dummy value, a symbol is always one.
        self.val = 1.0

        # Initialise variable, type and class.
        self.v = variable
        self.t = symbol_type
        self._prec = 1

        # Needed for symbols like std::cos(x*y + z),
        # where base_expr = x*y + z.
        # ops = base_expr.ops() + base_ops = 2 + 1 = 3
        self.base_expr = base_expr
        self.base_op = base_op
        self.exp = expo
        self.cond = cond

        # If type of the base_expr is lower than the given symbol_type change type.
        # TODO: Should we raise an error here? Or simply require that one
        # initalise the symbol by Symbol('std::cos(x*y)', (x*y).t, x*y, 1).
        if base_expr and base_expr.t < self.t:
            self.t = base_expr.t

        # Compute the representation now, such that we can use it directly
        # in the __eq__ and __ne__ methods (improves performance a bit, but
        # only when objects are cached).
        if self.base_expr and self.exp is None:
            self._repr = "Symbol('%s', %s, %s, %d)" % (self.v, type_to_string[self.t],\
                         self.base_expr._repr, self.base_op)
        elif self.base_expr:
            self._repr = "Symbol('%s', %s, %s, %d, %s)" % (self.v, type_to_string[self.t],\
                         self.base_expr._repr, self.base_op, self.exp)
        elif self.cond:
            self._repr = "Symbol('%s', %s, %s, %d, %s, %s)" % (self.v, type_to_string[self.t],\
                          self.base_expr, self.base_op, self.exp, self.cond)
        else:
            self._repr = "Symbol('%s', %s)" % (self.v, type_to_string[self.t])

        # Use repr as hash value.
        self._hash = hash(self._repr)

    # Print functions.
    def __str__(self):
        "Simple string representation which will appear in the generated code."
        if self.base_expr is None:
            if self.cond == ():
                return self.v
            else:
                if len(self.cond) == 2:
                    return self.cond[1](str(self.cond[0]))
                return "".join([str(c) for c in self.cond])
        elif self.exp is None:
            return self.v(str(self.base_expr))
        return self.v(str(self.base_expr), self.exp)

    # Binary operators.
    def __add__(self, other):
        "Addition by other objects."
        # NOTE: We expect expanded objects
        # symbols, if other is a product, try to let product handle the addition.
        # Returns x + x -> 2*x, x + 2*x -> 3*x.
        if self._repr == other._repr:
            return create_product([create_float(2), self])
        elif other._prec == 2: # prod
            return other.__add__(self)
        return create_sum([self, other])

    def __sub__(self, other):
        "Subtract other objects."
        # NOTE: We expect expanded objects
        # symbols, if other is a product, try to let product handle the addition.
        if self._repr == other._repr:
            return create_float(0)
        elif other._prec == 2: # prod
            if other.get_vrs() == (self,):
                return create_product([create_float(1.0 - other.val), self]).expand()
        return create_sum([self, create_product([create_float(-1), other])])

    def __mul__(self, other):
        "Multiplication by other objects."
        # NOTE: We assume expanded objects.
        # If product will be zero.
        if self.val == 0.0 or other.val == 0.0:
            return create_float(0)

        # If other is Sum or Fraction let them handle the multiply.
        if other._prec in (3, 4): # sum or frac
            return other.__mul__(self)

        # If other is a float or symbol, create simple product.
        if other._prec in (0, 1): # float or sym
            return create_product([self, other])

        # Else add variables from product.
        return create_product([self] + other.vrs)

    def __div__(self, other):
        "Division by other objects."
        # NOTE: We assume expanded objects.
        # If division is illegal (this should definitely not happen).
        if other.val == 0.0:
            error("Division by zero.")

        # Return 1 if the two symbols are equal.
        if self._repr == other._repr:
            return create_float(1)

        # If other is a Sum we can only return a fraction.
        # TODO: Refine this later such that x / (x + x*y) -> 1 / (1 + y)?
        if other._prec == 3: # sum
            return create_fraction(self, other)

        # Handle division by FloatValue, Symbol, Product and Fraction.
        # Create numerator and list for denominator.
        num = [self]
        denom = []

        # Add floatvalue, symbol and products to the list of denominators.
        if other._prec in (0, 1): # float or sym
            denom = [other]
        elif other._prec == 2: # prod
            # Need copies, so can't just do denom = other.vrs.
            denom += other.vrs
        # fraction.
        else:
            # TODO: Should we also support division by fraction for generality?
            # It should not be needed by this module.
            error("Did not expected to divide by fraction.")

        # Remove one instance of self in numerator and denominator if
        # present in denominator i.e., x/(x*y) --> 1/y.
        if self in denom:
            denom.remove(self)
            num.remove(self)

        # Loop entries in denominator and move float value to numerator.
        for d in denom:
            # Add the inverse of a float to the numerator, remove it from
            # the denominator and continue.
            if d._prec == 0: # float
                num.append(create_float(1.0/other.val))
                denom.remove(d)
                continue

        # Create appropriate return value depending on remaining data.
        # Can only be for x / (2*y*z) -> 0.5*x / (y*z).
        if len(num) > 1:
            num = create_product(num)
        # x / (y*z) -> x/(y*z),
        elif num:
            num = num[0]
        # else x / (x*y) -> 1/y.
        else:
            num = create_float(1)

        # If we have a long denominator, create product and fraction.
        if len(denom) > 1:
            return create_fraction(num, create_product(denom))
        # If we do have a denominator, but only one variable don't create a
        # product, just return a fraction using the variable as denominator.
        elif denom:
            return create_fraction(num, denom[0])
        # If we don't have any donominator left, return the numerator.
        # x / 2.0 -> 0.5*x.
        return num.expand()

    # Public functions.
    def get_unique_vars(self, var_type):
        "Get unique variables (Symbols) as a set."
        # Return self if type matches, also return base expression variables.
        s = set()
        if self.t == var_type:
            s.add(self)
        if self.base_expr:
            s.update(self.base_expr.get_unique_vars(var_type))
        return s

    def get_var_occurrences(self):
        """Determine the number of times all variables occurs in the expression.
        Returns a dictionary of variables and the number of times they occur."""
        # There is only one symbol.
        return {self:1}

    def ops(self):
        "Returning the number of floating point operation for symbol."
        # Get base ops, typically 1 for sin() and then add the operations
        # for the base (sin(2*x + 1)) --> 2 + 1.
        if self.base_expr:
            return self.base_op + self.base_expr.ops()
        elif self.cond:
            if len(self.cond) == 2:
                return self.base_op + self.cond[0].ops() + 1
            return self.base_op + self.cond[0].ops() + self.cond[2].ops() + 1
        return self.base_op

from floatvalue import FloatValue
from product    import Product
from sumobj    import Sum
from fraction   import Fraction