def visit_Num(self, n): try: d = self.context.constants[type(n.n)] return d[n.n][self.dialect] except KeyError: pass return str(math2.int_or_float(n.n))
def add(self, expr): ''' add expr :return: bool True if it has been added ''' if expr is None: return False try: k = expr() # the key is the numeric value of expr except (TypeError, ValueError): return False if not math2.is_number(k): return False if type(k) is complex: return False if self.int: # limit to integers... but maybe we're extremely close k = math2.int_or_float(k) if not isinstance(k, int): return False if k < 0: return self.add(-expr) if self.max is not None and k > self.max: return False if k in self: if self.improve and expr.complexity() >= self[k].complexity(): return False self[k] = expr return True
def div(a, b): res = math2.int_or_float(a / b) a2 = res * b if a == a2: return res # the division has rounded something, like (a+eps)/a =1 # numpy.nextafter(res,res+math2.sign(a)*math2.sign(b)) return res + math2.eps * math2.sign(a * b)
def friedman(num): for e in gen(num): try: n = math2.int_or_float(e()) # cope with potential rounding problems if n == num and str(e) != str(num): # concat is too easy ... yield (num, e) except GeneratorExit: # https://stackoverflow.com/a/41115661/1395973 return except: pass
def friedman(num): for e in gen(num): try: # cope with potential rounding problems n = math2.int_or_float(e()) if n == num and str(e) != str(num): # concat is too easy ... yield (num, e) except GeneratorExit: # https://stackoverflow.com/a/41115661/1395973 return except: pass
def eval(self, node): '''safe eval of ast node : only functions and _operators listed above can be used :param node: ast.AST to evaluate :param ctx: dict of varname : value to substitute in node :return: number or expression string ''' if isinstance(node, ast.Num): # <number> return node.n elif isinstance(node, ast.Name): return self.variables.get(node.id, node.id) # return value or var elif isinstance(node, ast.Attribute): return getattr(self.variables, [node.value.id], node.attr) elif isinstance(node, ast.Tuple): return tuple(self.eval(e) for e in node.elts) elif isinstance(node, ast.Call): params = [self.eval(arg) for arg in node.args] if node.func.id not in self.functions: raise NameError('%s function not allowed' % node.func.id) f = self.functions[node.func.id][0] res = f(*params) # try to correct small error return math2.int_or_float(res, 0, 1e-12) elif isinstance(node, ast.BinOp): # <left> <operator> <right> op = self.operators[type(node.op)] left = self.eval(node.left) right = self.eval(node.right) if math2.is_number(left) and math2.is_number(right): res = op[0](left, right) # no correction here ! return res else: return "%s%s%s" % (left, op[_dialect_python], right) elif isinstance(node, ast.UnaryOp): # <operator> <operand> e.g., -1 right = self.eval(node.operand) return self.operators[type(node.op)][0](right) elif isinstance(node, ast.Compare): left = self.eval(node.left) for op, right in zip(node.ops, node.comparators): # TODO: find what to do when multiple items in list return self.operators[type(op)][0](left, self.eval(right)) elif isinstance(node, ast.NameConstant): return node.value else: logging.warning(ast.dump(node, False, False)) return self.eval(node.body) # last chance
def eval(self, node): '''safe eval of ast node : only functions and _operators listed above can be used :param node: ast.AST to evaluate :param ctx: dict of varname : value to substitute in node :return: number or expression string ''' if isinstance(node, ast.Num): # <number> return node.n elif isinstance(node, ast.Name): return self.variables.get(node.id, node.id) # return value or var elif isinstance(node, ast.Attribute): return getattr(self[node.value.id], node.attr) elif isinstance(node, ast.Tuple): return tuple(self.eval(e) for e in node.elts) elif isinstance(node, ast.Call): params = [self.eval(arg) for arg in node.args] if not node.func.id in self.functions: raise NameError('%s function not allowed' % node.func.id) f = self.functions[node.func.id][0] res = f(*params) return math2.int_or_float(res, 0, 1e-12) # try to correct small error elif isinstance(node, ast.BinOp): # <left> <operator> <right> op = self.operators[type(node.op)] left = self.eval(node.left) right = self.eval(node.right) if math2.is_number(left) and math2.is_number(right): res = op[0](left, right) # no correction here ! return res else: return "%s%s%s" % (left, op[_dialect_python], right) elif isinstance(node, ast.UnaryOp): # <operator> <operand> e.g., -1 right = self.eval(node.operand) return self.operators[type(node.op)][0](right) elif isinstance(node, ast.Compare): left = self.eval(node.left) for op, right in zip(node.ops, node.comparators): # TODO: find what to do when multiple items in list return self.operators[type(op)][0](left, self.eval(right)) elif isinstance(node, ast.NameConstant): return node.value else: logging.warning(ast.dump(node, False, False)) return self.eval(node.body) # last chance
def div(a, b): res = math2.int_or_float(a / b) a2 = res * b if a == a2: return res # the division has rounded something, like (a+eps)/a =1 return res + math2.eps * math2.sign(a * b) # numpy.nextafter(res,res+math2.sign(a)*math2.sign(b))