def sympy_to_elementlist(expr): numer, denom = expr.as_numer_denom() if denom != 1: return formula.ElementList([ formula.Frac( sympy_to_elementlist(numer).elements, sympy_to_elementlist(denom).elements) ]) elif isinstance(expr, sympy.Symbol): return formula.ElementList([formula.Atom(expr.name)]) elif expr is sympy.pi: return formula.ElementList([formula.Atom('π')]) elif expr is sympy.E: return formula.ElementList([formula.Atom('e')]) elif expr is sympy.I: return formula.ElementList([formula.Atom('i')]) elif isinstance(expr, sympy.Number): return formula.ElementList([ formula.BinaryOperatorAtom(ch) if ch == '-' else formula.Atom(ch) for ch in str(expr) ]) elif isinstance(expr, sympy.sin): return formula.ElementList([ formula.OperatorAtom('sin'), formula.Paren('('), *sympy_to_elementlist(expr.args[0]).elements, formula.Paren(')') ]) elif expr is sympy.cos: return formula.ElementList([formula.OperatorAtom('cos')]) elif isinstance(expr, sympy.Add): res = [] for arg in expr.args: res.extend(sympy_to_elementlist(arg).elements) res.append(formula.BinaryOperatorAtom('+')) del res[-1] return formula.ElementList(res) elif isinstance(expr, sympy.Mul): res = [] for arg in expr.args: if isinstance(arg, sympy.Add): res.append(formula.Paren('(')) res.extend(sympy_to_elementlist(arg).elements) if isinstance(arg, sympy.Add): res.append(formula.Paren(')')) return formula.ElementList(res) elif isinstance(expr, sympy.Pow): x = sympy_to_elementlist(expr.args[0]) supersub = formula.SuperscriptSubscript() supersub.exponent = sympy_to_elementlist(expr.args[1]) supersub.update_lists() return x + formula.ElementList([supersub]) else: raise NotImplementedError(expr.func)
def slider_changed(self, widget): self.editor.cursor.cancel_selection() equals_index = self.editor.expr.elements.index(formula.BinaryOperatorAtom("=")) del self.editor.expr.elements[equals_index+1:] cursor = self.editor.cursor cursor.reparent(self.editor.expr, -1) new_val = round(self.slider.get_value(), 4) for char in str(int(new_val) if new_val.is_integer() else new_val): if char == "-": self.editor.expr.insert(formula.BinaryOperatorAtom("−"), cursor) elif char.isdigit() or char == ".": self.editor.expr.insert(formula.Atom(char), cursor) self.editor.queue_draw() self.app.gl_area.queue_draw()
def elementlist_to_sympy(expr): if not expr: return None output = [] operators = [] prev = None for t in tokens(expr): # implicit multiplication if prev is not None \ and not isinstance(prev, (formula.BinaryOperatorAtom, formula.OperatorAtom)) \ and not isinstance(t, formula.BinaryOperatorAtom) \ and not is_paren(prev, left=True) \ and not is_paren(t, left=False): mult = formula.BinaryOperatorAtom("×") pop_operators(operators, output, precedence(mult)) operators.append(mult) if isinstance(t, sympy.Basic): output.append(t) elif isinstance(t, formula.OperatorAtom): operators.append(t) elif isinstance(t, formula.BinaryOperatorAtom): if prev is None or is_paren(prev, left=True) or \ isinstance(prev, (formula.BinaryOperatorAtom, formula.OperatorAtom)): # t is a unary prefix operator # it should only pop other prefix operators pop_operators(operators, output, precedence(t), only_unary=True) operators.append(formula.BinaryOperatorAtom("unary_minus")) else: # t is a binary or postfix unary operator pop_operators(operators, output, precedence(t)) operators.append(t) elif is_paren(t, left=True): operators.append(t) elif is_paren(t, left=False): pop_operators(operators, output, 1000) if operators and is_paren(operators[-1], left=True): operators.pop() else: output.append(element_to_sympy(t)) prev = t while operators: pop_operator(operators, output) if len(output) != 1: raise SyntaxError("Malformed expression") return output[0]
def tokens(elementlist): number = [] for elem, next in zip_longest(elementlist.elements, elementlist.elements[1:]): if part_of_number(elem): number.append(elem.name) if not part_of_number(next): yield sympy.Number("".join(number)) number = [] elif isinstance(elem, formula.Atom): yield atom_to_symbol(elem, next) elif isinstance(elem, formula.SuperscriptSubscript) and elem.exponent: yield formula.BinaryOperatorAtom("^") yield elementlist_to_sympy(elem.exponent) else: yield elem