[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Commit-gnuradio] r5582 - in grc/branches/jblum_work: notes src
From: |
jblum |
Subject: |
[Commit-gnuradio] r5582 - in grc/branches/jblum_work: notes src |
Date: |
Thu, 31 May 2007 12:37:02 -0600 (MDT) |
Author: jblum
Date: 2007-05-31 12:37:02 -0600 (Thu, 31 May 2007)
New Revision: 5582
Modified:
grc/branches/jblum_work/notes/notes.txt
grc/branches/jblum_work/src/Constants.py
grc/branches/jblum_work/src/DataType.py
grc/branches/jblum_work/src/MathExprParser.py
Log:
improved casting in math expression parser
Modified: grc/branches/jblum_work/notes/notes.txt
===================================================================
--- grc/branches/jblum_work/notes/notes.txt 2007-05-31 13:19:20 UTC (rev
5581)
+++ grc/branches/jblum_work/notes/notes.txt 2007-05-31 18:37:02 UTC (rev
5582)
@@ -21,6 +21,8 @@
-include dtd in saved flow graphs
-immediate display of tool tips in entry boxes
-help window for functions in the math expression parser
+-function to import taps from a file
+-fm demod example with expansion of wfm_recv block
############ wxPython Features: ####################
-dump wx running graph to png?
@@ -37,7 +39,6 @@
############ Uninteresting Features: ####################
-add the concept of a current working directory
-auto param to usrp diagnose dialog
--add a trim option for dangling sockets
-use popen3 once it works in cygwin
-arrow like images for socket, to replace in/out strings
-min/max in DataTypes can be other data types
Modified: grc/branches/jblum_work/src/Constants.py
===================================================================
--- grc/branches/jblum_work/src/Constants.py 2007-05-31 13:19:20 UTC (rev
5581)
+++ grc/branches/jblum_work/src/Constants.py 2007-05-31 18:37:02 UTC (rev
5582)
@@ -152,7 +152,7 @@
# A state is recorded for each change to the flow graph, the size
dictates how many states we can record
######################################################################################################
-""" The size of the state saving cache in the gFloGraph (for undo/redo
functionality) """
+""" The size of the state saving cache in the flow graph (for undo/redo
functionality) """
STATE_CACHE_SIZE = 42
######################################################################################################
Modified: grc/branches/jblum_work/src/DataType.py
===================================================================
--- grc/branches/jblum_work/src/DataType.py 2007-05-31 13:19:20 UTC (rev
5581)
+++ grc/branches/jblum_work/src/DataType.py 2007-05-31 18:37:02 UTC (rev
5582)
@@ -82,12 +82,11 @@
base_type = 'number'
def parse(self):
''' Evaluate the math expressions in the data type. '''
- elements = MathExprParser.eval_expr(DataType.parse(self))
- if len(elements) == 1: num = elements[0]
- else: raise SyntaxError('Expected a single number.')
+ num = MathExprParser.eval_expr(DataType.parse(self))
parsed = self.parser(num)
self.verify_bounds(parsed)
return parsed
+
class Int(Number):
''' The integer data type. '''
type = 'int'
@@ -120,7 +119,7 @@
num_bytes = gr.sizeof_gr_complex
def parser(self, value):
''' Return the value as complex. '''
- return complex(value)
+ return MathExprParser.verify_complex(value)
#############################################################################################
# Special Types
@@ -271,6 +270,7 @@
def parse(self):
''' Verify that the length of the vector is within bounds.
'''
elements = MathExprParser.eval_expr(DataType.parse(self))
+ if type(elements) != type(list()): elements = [elements]
#ensure that elements is a list
self.verify_bounds(len(elements))
return map(lambda v: self.parser(v), elements)
Modified: grc/branches/jblum_work/src/MathExprParser.py
===================================================================
--- grc/branches/jblum_work/src/MathExprParser.py 2007-05-31 13:19:20 UTC
(rev 5581)
+++ grc/branches/jblum_work/src/MathExprParser.py 2007-05-31 18:37:02 UTC
(rev 5582)
@@ -19,25 +19,22 @@
"""
MathExprParser.py
Josh Blum
- Take a sting containing numbers, floats, complex
- and operators and parse it into a single answer.
+ This file provides:
+ eval_expr for evaluating string expressions,
+ verify_complex, verify_float, verify_int for casting numbers.
"""
import math,cmath
from gnuradio import gr
-def _number(value='0'):
- ''' The parser method used for numeric entries. '''
- return complex(value)
-
_ORDER_OF_OPS = ('^-', '^', '*', '/', '-', '+')
_WHITESPACE = (' ', '\t', '')
_CONSTANTS = { #constans must be lower case
- 'pi' : _number(cmath.pi),
- 'e' : _number(cmath.e),
- 'j' : _number(1j),
+ 'pi' : complex(cmath.pi),
+ 'e' : complex(cmath.e),
+ 'j' : complex(1j),
'hamming' : gr.firdes.WIN_HAMMING, #filter windows
'hann' : gr.firdes.WIN_HANN,
@@ -50,17 +47,24 @@
## Complex mathematical functions
#########################################################
+def verify_complex(num):
+ ''' Verify that the number is indeed a number.
+ Raise an exception if number cannot be cast to a complex.
+ Return the value as a complex. '''
+ try: c_num = complex(num) #ensure that the num can be complex
+ except: raise ValueError('"%s" is not a number.'%(num,))
+ return c_num
+
def verify_float(num):
- ''' Verify that the complex number has no imaginary part.
+ ''' Verify that the number has no imaginary part.
Raise an exception if the imaginary part is non zero.
Return the value as a float. '''
- try: c_num = complex(num) #ensure that the num can be complex
- except ValueError: raise ValueError('"%s" is not a number.'%(num,))
- if num.imag != 0: raise ValueError('Expected a float but found
"%s".'%(c_num,))
+ c_num = verify_complex(num) #ensure that the num can be complex
+ if c_num.imag != 0: raise ValueError('Expected a float but found
"%s".'%(c_num,))
return float(c_num.real)
def verify_int(num):
- ''' Verify that the complex number has no imaginary part.
+ ''' Verify that the number has no imaginary part.
Verify that the complex number has no decimal part.
Otherwise raise an exception.
Return the value as a int '''
@@ -73,15 +77,15 @@
sum = 0
for arg in args:
if _is_list(arg): sum = sum + _complex_abs_v(*arg)
- else: sum = sum + arg.real*arg.real + arg.imag*arg.imag
- return _number(sum**0.5)
+ else: sum = sum + complex(arg).real*complex(arg).real +
complex(arg).imag*complex(arg).imag
+ return complex(sum**0.5)
def _complex_real_v(*args):
''' Get the real part of a number or vector. '''
result = list()
for arg in args:
if _is_list(arg): result.append(_complex_real_v(*arg))
- else: result.append(_number(arg.real))
+ else: result.append(complex(complex(arg).real))
return result
def _complex_imag_v(*args):
@@ -89,7 +93,7 @@
result = list()
for arg in args:
if _is_list(arg): result.append(_complex_imag_v(*arg))
- else: result.append(_number(arg.real))
+ else: result.append(complex(complex(arg).imag))
return result
def _complex_conj_v(*args):
@@ -97,12 +101,12 @@
result = list()
for arg in args:
if _is_list(arg): result.append(_complex_conj_v(*arg))
- else: result.append(_number(arg.conjugate()))
+ else: result.append(complex(complex(arg).conjugate()))
return result
def _complex_arg(arg):
''' Get the angle of the complex number (radians). '''
- return _number(math.atan2(arg.imag, arg.real))
+ return complex(math.atan2(complex(arg).imag, complex(arg).real))
def _handle_filter(filter, *filter_args):
''' Pass the filter arguments to the filter function.
@@ -130,7 +134,10 @@
for i,arg in enumerate(filter_args):
if i in floats: filter_args[i] = verify_float(arg)
if i in ints: filter_args[i] = verify_int(arg)
- return list(filter(*filter_args))
+ taps = list(filter(*filter_args))
+ # convert all taps to complex #
+ for i,tap in enumerate(taps): taps[i] = complex(tap)
+ return taps
_FUNCTIONS = {
'pow' : lambda b, p: b**p,
@@ -174,52 +181,13 @@
'root_raised_cosine' : lambda *args:
_handle_filter(gr.firdes.root_raised_cosine, *args),
'window' : lambda *args: _handle_filter(gr.firdes.window, *args),
- 'floor' : lambda f: _number(math.floor(verify_float(f))),
- 'ceil' : lambda f: _number(math.ceil(verify_float(f))),
- 'radians' : lambda f: _number(math.radians(verify_float(f))),
- 'degrees' : lambda f: _number(math.degrees(verify_float(f))),
- 'fmod' : lambda f1, f2: _number(math.fmod(verify_float(f1),
verify_float(f2))),
+ 'floor' : lambda f: complex(math.floor(verify_float(f))),
+ 'ceil' : lambda f: complex(math.ceil(verify_float(f))),
+ 'radians' : lambda f: complex(math.radians(verify_float(f))),
+ 'degrees' : lambda f: complex(math.degrees(verify_float(f))),
+ 'fmod' : lambda f1, f2: complex(math.fmod(verify_float(f1),
verify_float(f2))),
}
-def _handle_operation(op, arg1, arg2):
- ''' Handle basic operations specified in the order of operations.
- All calculations are complex, some vector operations are
supported.
- Return the number/list representing the result. '''
- if op not in _ORDER_OF_OPS: raise NameError('Unknown operator:
"%s".'%(op))
- arg1_is_list = _is_list(arg1)
- arg2_is_list = _is_list(arg2)
- # addition and subtraction of vectors #
- if arg1_is_list and arg2_is_list and \
- len(arg1) == len(arg2) and op in ('+', '-'):
- result = list()
- for i,arg1_elem in enumerate(arg1):
- arg2_elem = arg2[i]
- result.append(_handle_operation(op, arg1_elem,
arg2_elem))
- return result
- # scalar times vector #
- if not arg1_is_list and arg2_is_list and op == '*':
- return map(lambda elem: _handle_operation(op, arg1, elem), arg2)
- # vector times/divided scalar #
- if arg1_is_list and not arg2_is_list and op in ('*', '/'):
- return map(lambda elem: _handle_operation(op, elem, arg2), arg1)
- # non vectored operations #
- if not arg1_is_list and not arg2_is_list and \
- type(_number()) == type(arg1) == type(arg2): #non vector
operations
- if op == '^-':
- return arg1**(-1*arg2)
- elif op == '^':
- return arg1**arg2
- elif op == '*':
- return arg1 * arg2
- elif op == '/':
- try: return arg1 / arg2
- except ZeroDivisionError: raise
ZeroDivisionError('Cannot divide "%s" by 0.'%(arg1,))
- elif op == '+':
- return arg1 + arg2
- elif op == '-':
- return arg1 - arg2
- raise ArithmeticError('Operation of "%s" cannot be performed on "%s",
"%s".'%(op, arg1, arg2))
-
#########################################################
## Boolean tests for special characters and symbols
#########################################################
@@ -231,7 +199,7 @@
def _is_constant(symbol): return symbol in _CONSTANTS.keys()
def _is_number(symbol):
- try: _number(symbol)
+ try: complex(symbol)
except: return False
return True
@@ -266,6 +234,49 @@
}[bracket]
#########################################################
+## Symbolic operations
+#########################################################
+
+def _handle_operation(op, arg1, arg2):
+ ''' Handle basic operations specified in the order of operations.
+ All calculations are complex, some vector operations are
supported.
+ Return the number/list representing the result. '''
+ if op not in _ORDER_OF_OPS: raise NameError('Unknown operator:
"%s".'%(op))
+ arg1_is_list = _is_list(arg1)
+ arg2_is_list = _is_list(arg2)
+ # addition and subtraction of vectors #
+ if arg1_is_list and arg2_is_list and \
+ len(arg1) == len(arg2) and op in ('+', '-'):
+ result = list()
+ for i,arg1_elem in enumerate(arg1):
+ arg2_elem = arg2[i]
+ result.append(_handle_operation(op, arg1_elem,
arg2_elem))
+ return result
+ # scalar times vector #
+ if not arg1_is_list and arg2_is_list and op == '*':
+ return map(lambda elem: _handle_operation(op, arg1, elem), arg2)
+ # vector times/divided scalar #
+ if arg1_is_list and not arg2_is_list and op in ('*', '/'):
+ return map(lambda elem: _handle_operation(op, elem, arg2), arg1)
+ # non vectored operations #
+ if not arg1_is_list and not arg2_is_list and \
+ _is_number(arg1) and _is_number(arg2): #non vector operations
+ if op == '^-':
+ return arg1**(-1*arg2)
+ elif op == '^':
+ return arg1**arg2
+ elif op == '*':
+ return arg1 * arg2
+ elif op == '/':
+ try: return arg1 / arg2
+ except ZeroDivisionError: raise
ZeroDivisionError('Cannot divide "%s" by 0.'%(arg1,))
+ elif op == '+':
+ return arg1 + arg2
+ elif op == '-':
+ return arg1 - arg2
+ raise ArithmeticError('Operation of "%s" cannot be performed on "%s",
"%s".'%(op, arg1, arg2))
+
+#########################################################
## Evaluate the expression string
#########################################################
@@ -342,7 +353,7 @@
# substitute in values for constants #
elif _is_constant(element): nested_elements[i] =
_CONSTANTS[element]
# substitute in values for numbers #
- elif _is_number(element): nested_elements[i] = _number(element)
+ elif _is_number(element): nested_elements[i] = complex(element)
# handle functions #
for function in _FUNCTIONS.keys():
while function in nested_elements:
@@ -384,7 +395,7 @@
elif _is_comma(element) and _is_comma(last_element):
raise SyntaxError('Commas must be separated by
non-commas.')
last_element = element
- if len(vector) == 1 and not _is_comma(last_element) and not
_is_list(vector[0]): return vector[0] #return single number
+ if len(vector) == 1 and not _is_comma(last_element): return vector[0]
#return single number
return vector #otherwise return vector
def eval_expr(expr_str):
@@ -398,7 +409,6 @@
nested_elements = _nest_elements(rectified_elements)
#print "nested", nested_elements
simplified = _simplify_nested_elements(nested_elements)
- if not _is_list(simplified): simplified = [simplified] #keep it in
list form
return simplified
if __name__ == '__main__':
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Commit-gnuradio] r5582 - in grc/branches/jblum_work: notes src,
jblum <=