Commit 6304feef by Piotr Mitros

Calculator changes for Anant

parent 81e1a8dc
import copy
import math import math
import operator import operator
import numpy
from pyparsing import Word, alphas, nums, oneOf, Literal from pyparsing import Word, alphas, nums, oneOf, Literal
from pyparsing import ZeroOrMore, OneOrMore, StringStart from pyparsing import ZeroOrMore, OneOrMore, StringStart
from pyparsing import StringEnd, Optional, Forward from pyparsing import StringEnd, Optional, Forward
from pyparsing import CaselessLiteral, Group, StringEnd from pyparsing import CaselessLiteral, Group, StringEnd
from pyparsing import NoMatch, stringEnd from pyparsing import NoMatch, stringEnd
default_functions = {'sin' : numpy.sin,
'cos' : numpy.cos,
'tan' : numpy.tan,
'sqrt': numpy.sqrt,
'log10':numpy.log10,
'log2':numpy.log2,
'ln': numpy.log,
'arccos':numpy.arccos,
'arcsin':numpy.arcsin,
'arctan':numpy.arctan,
'abs':numpy.abs
}
default_variables = {'j':numpy.complex(0,1),
'e':numpy.complex(numpy.e)
}
def evaluator(variables, functions, string): def evaluator(variables, functions, string):
''' Evaluate an expression. Variables are passed as a dictionary ''' Evaluate an expression. Variables are passed as a dictionary
from string to value. Unary functions are passed as a dictionary from string to value. Unary functions are passed as a dictionary
from string to function ''' from string to function '''
all_variables = copy.copy(default_variables)
all_variables.update(variables)
all_functions = copy.copy(default_functions)
all_functions.update(functions)
if string.strip() == "": if string.strip() == "":
return float('nan') return float('nan')
ops = { "^" : operator.pow, ops = { "^" : operator.pow,
...@@ -38,7 +62,7 @@ def evaluator(variables, functions, string): ...@@ -38,7 +62,7 @@ def evaluator(variables, functions, string):
def number_parse_action(x): # [ '7' ] -> [ 7 ] def number_parse_action(x): # [ '7' ] -> [ 7 ]
return [super_float("".join(x))] return [super_float("".join(x))]
def exp_parse_action(x): # [ 2 ^ 3 ^ 2 ] -> 512 def exp_parse_action(x): # [ 2 ^ 3 ^ 2 ] -> 512
x = [e for e in x if type(e) == float] # Ignore ^ x = [e for e in x if type(e) in [float, numpy.float64, numpy.complex]] # Ignore ^
x.reverse() x.reverse()
x=reduce(lambda a,b:b**a, x) x=reduce(lambda a,b:b**a, x)
return x return x
...@@ -68,7 +92,7 @@ def evaluator(variables, functions, string): ...@@ -68,7 +92,7 @@ def evaluator(variables, functions, string):
prod=op(prod, e) prod=op(prod, e)
return prod return prod
def func_parse_action(x): def func_parse_action(x):
return [functions[x[0]](x[1])] return [all_functions[x[0]](x[1])]
number_suffix=reduce(lambda a,b:a|b, map(Literal,suffixes.keys()), NoMatch()) # SI suffixes and percent number_suffix=reduce(lambda a,b:a|b, map(Literal,suffixes.keys()), NoMatch()) # SI suffixes and percent
(dot,minus,plus,times,div,lpar,rpar,exp)=map(Literal,".-+*/()^") (dot,minus,plus,times,div,lpar,rpar,exp)=map(Literal,".-+*/()^")
...@@ -94,14 +118,14 @@ def evaluator(variables, functions, string): ...@@ -94,14 +118,14 @@ def evaluator(variables, functions, string):
# Handle variables passed in. E.g. if we have {'R':0.5}, we make the substitution. # Handle variables passed in. E.g. if we have {'R':0.5}, we make the substitution.
# Special case for no variables because of how we understand PyParsing is put together # Special case for no variables because of how we understand PyParsing is put together
if len(variables)>0: if len(all_variables)>0:
varnames = sreduce(lambda x,y:x|y, map(lambda x: CaselessLiteral(x), variables.keys())) varnames = sreduce(lambda x,y:x|y, map(lambda x: CaselessLiteral(x), all_variables.keys()))
varnames.setParseAction(lambda x:map(lambda y:variables[y], x)) varnames.setParseAction(lambda x:map(lambda y:all_variables[y], x))
else: else:
varnames=NoMatch() varnames=NoMatch()
# Same thing for functions. # Same thing for functions.
if len(functions)>0: if len(all_functions)>0:
funcnames = sreduce(lambda x,y:x|y, map(lambda x: CaselessLiteral(x), functions.keys())) funcnames = sreduce(lambda x,y:x|y, map(lambda x: CaselessLiteral(x), all_functions.keys()))
function = funcnames+lpar.suppress()+expr+rpar.suppress() function = funcnames+lpar.suppress()+expr+rpar.suppress()
function.setParseAction(func_parse_action) function.setParseAction(func_parse_action)
else: else:
...@@ -119,7 +143,7 @@ def evaluator(variables, functions, string): ...@@ -119,7 +143,7 @@ def evaluator(variables, functions, string):
if __name__=='__main__': if __name__=='__main__':
variables={'R1':2.0, 'R3':4.0} variables={'R1':2.0, 'R3':4.0}
functions={'sin':math.sin, 'cos':math.cos} functions={'sin':numpy.sin, 'cos':numpy.cos}
print "X",evaluator(variables, functions, "10000||sin(7+5)-6k") print "X",evaluator(variables, functions, "10000||sin(7+5)-6k")
print "X",evaluator(variables, functions, "13") print "X",evaluator(variables, functions, "13")
print evaluator({'R1': 2.0, 'R3':4.0}, {}, "13") print evaluator({'R1': 2.0, 'R3':4.0}, {}, "13")
......
...@@ -25,7 +25,7 @@ def calculate(request): ...@@ -25,7 +25,7 @@ def calculate(request):
'equation':equation} 'equation':equation}
track.views.server_track(request, 'error:calc', event, page='calc') track.views.server_track(request, 'error:calc', event, page='calc')
return HttpResponse(json.dumps({'result':'Invalid syntax'})) return HttpResponse(json.dumps({'result':'Invalid syntax'}))
return HttpResponse(json.dumps({'result':result})) return HttpResponse(json.dumps({'result':str(result)}))
def send_feedback(request): def send_feedback(request):
''' Feeback mechanism in footer of every page. ''' ''' Feeback mechanism in footer of every page. '''
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment