From 7a99f13d8107258dd3a8d1cae35a20397c81eebe Mon Sep 17 00:00:00 2001 From: NicholasBermuda Date: Mon, 26 Jun 2017 16:32:09 +0100 Subject: [PATCH 01/10] complex isnan --- coffee/base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/coffee/base.py b/coffee/base.py index c8f4d030..69a3fdb4 100644 --- a/coffee/base.py +++ b/coffee/base.py @@ -36,7 +36,7 @@ from __future__ import absolute_import, print_function, division from copy import deepcopy as dcopy -from math import isnan +from cmath import isnan import numbers import numpy as np @@ -468,7 +468,7 @@ def is_const(self): @property def is_number(self): try: - float(self.symbol) + complex(self.symbol) return True except ValueError: return False From 00eed5762b4e6f38e98bc8980901678ec6d17f4f Mon Sep 17 00:00:00 2001 From: NicholasBermuda Date: Fri, 30 Jun 2017 23:26:18 +0100 Subject: [PATCH 02/10] fix a function description --- coffee/base.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/coffee/base.py b/coffee/base.py index 69a3fdb4..1b4b27ea 100644 --- a/coffee/base.py +++ b/coffee/base.py @@ -259,20 +259,22 @@ def values(self, val): self._values = val def _formatter(self, v): - """Format a float into a string, showing up to ``precision`` decimal digits. + """Format a complex into a string, showing up to ``precision`` decimal digits. This function is partly extracted from the open_source "FFC: the FEniCS Form Compiler", freely accessible at https://bitbucket.org/fenics-project/ffc.""" f = "%%.%dg" % self.precision f_int = "%%.%df" % 1 eps = 10.0**(-self.precision) + vr = v.real + vi = v.imag if not isinstance(v, numbers.Number): return v.gencode(not_scope=True) elif isnan(v): return "NAN" - elif abs(v - round(v, 1)) < eps: - return f_int % v + elif abs(vr - round(vr, 1)) < eps and abs(vi - round(vi, 1)) < eps: + return f_int % vr + ' + ' + f_int % vi + ' * I' else: - return f % v + return f % vr + ' + ' + f % vi + ' * I' def _tabulate_values(self, arr): if len(arr.shape) == 1: From 5a64937a5e3c841b78f4a73322319702ab58cd71 Mon Sep 17 00:00:00 2001 From: NicholasBermuda Date: Fri, 4 Aug 2017 20:07:48 +0200 Subject: [PATCH 03/10] add parens around complex numbers --- coffee/base.py | 1 + 1 file changed, 1 insertion(+) diff --git a/coffee/base.py b/coffee/base.py index 1b4b27ea..fbd63d4c 100644 --- a/coffee/base.py +++ b/coffee/base.py @@ -171,6 +171,7 @@ def __deepcopy__(self, memo): def gencode(self, not_scope=True, parent=None): children = [n.gencode(not_scope, self) for n in self.children] + children = ["("+child+")" for child in children if " * I" in child] subtree = (" "+type(self).op+" ").join(children) if parent: return wrap(subtree) From 23075a2f56dd91b039c06528c8010f230f4ba9e9 Mon Sep 17 00:00:00 2001 From: NicholasBermuda Date: Sat, 5 Aug 2017 17:09:16 +0200 Subject: [PATCH 04/10] better paren wrapping --- coffee/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coffee/base.py b/coffee/base.py index fbd63d4c..7f032f79 100644 --- a/coffee/base.py +++ b/coffee/base.py @@ -171,7 +171,7 @@ def __deepcopy__(self, memo): def gencode(self, not_scope=True, parent=None): children = [n.gencode(not_scope, self) for n in self.children] - children = ["("+child+")" for child in children if " * I" in child] + children = ["("+child+")" for child in children] subtree = (" "+type(self).op+" ").join(children) if parent: return wrap(subtree) From 1c724146c4499e9e461437695c04b2dafe322788 Mon Sep 17 00:00:00 2001 From: NicholasBermuda Date: Wed, 9 Aug 2017 18:39:57 +0200 Subject: [PATCH 05/10] symbol handling for nonnumeric symbols --- coffee/base.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/coffee/base.py b/coffee/base.py index 7f032f79..367116ae 100644 --- a/coffee/base.py +++ b/coffee/base.py @@ -266,16 +266,14 @@ def _formatter(self, v): f = "%%.%dg" % self.precision f_int = "%%.%df" % 1 eps = 10.0**(-self.precision) - vr = v.real - vi = v.imag if not isinstance(v, numbers.Number): return v.gencode(not_scope=True) elif isnan(v): return "NAN" - elif abs(vr - round(vr, 1)) < eps and abs(vi - round(vi, 1)) < eps: - return f_int % vr + ' + ' + f_int % vi + ' * I' + elif abs(v.real - round(v.real, 1)) < eps and abs(v.imag - round(v.imag, 1)) < eps: + return f_int % v.real + ' + ' + f_int % v.imag + ' * I' else: - return f % vr + ' + ' + f % vi + ' * I' + return f % v.real + ' + ' + f % v.imag + ' * I' def _tabulate_values(self, arr): if len(arr.shape) == 1: From ecd02c1755ed6e68a97a4c6be7f5c1afd1bff07c Mon Sep 17 00:00:00 2001 From: NicholasBermuda Date: Wed, 9 Aug 2017 18:40:13 +0200 Subject: [PATCH 06/10] update test to reflect new parens in binops --- tests/test_precedence.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_precedence.py b/tests/test_precedence.py index e30d82a7..7566b37a 100644 --- a/tests/test_precedence.py +++ b/tests/test_precedence.py @@ -6,10 +6,10 @@ def test_prod_div(): tree = ast.Prod("a", ast.Div("1", "b")) - assert tree.gencode() == "a * (1 / b)" + assert tree.gencode() == "(a) * (((1) / (b)))" def test_unary_op(): tree = ast.Not(ast.Or("a", ast.And("b", "c"))) - assert tree.gencode() == "!(a || (b && c))" + assert tree.gencode() == "!((a) || (((b) && (c))))" From 4a4e7969677983e28a2f58b44c40ff8c25ec6853 Mon Sep 17 00:00:00 2001 From: NicholasBermuda Date: Thu, 17 Aug 2017 22:00:53 +0100 Subject: [PATCH 07/10] new ComplexInvert to invert complex matrices; to be removed later --- coffee/base.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/coffee/base.py b/coffee/base.py index 367116ae..a466ca1f 100644 --- a/coffee/base.py +++ b/coffee/base.py @@ -1154,6 +1154,34 @@ def gencode(self, not_scope=True): """ % (str(dim), str(lda), str(sym), str(sym)) +class ComplexInvert(Statement, LinAlg): + """In-place inversion of a square array.""" + # this should probably be changed later to not require a real and complex version + def __init__(self, sym, dim, pragma=None): + super(ComplexInvert, self).__init__([sym, dim, dim], pragma) + + def reconstruct(self, sym, dim, **kwargs): + return type(self)(sym, dim, **kwargs) + + def operands(self): + return [self.children[0], self.children[1]], {'pragma': self.pragma} + + def gencode(self, not_scope=True): + sym, dim, lda = self.children + return """{ + int n = %s; + int lda = %s; + int ipiv[n]; + int lwork = n*n; + double complex work[lwork]; + int info; + + zgetrf_(&n,&n,%s,&lda,ipiv,&info); + zgetri_(&n,%s,&lda,ipiv,work,&lwork,&info); +} +""" % (str(dim), str(lda), str(sym), str(sym)) + + class Determinant(Expr, LinAlg): """Generic determinant""" def __init__(self, sym, pragma=None): From 24f5be8640c353299dbf76213a0b0e58cd6ce5d0 Mon Sep 17 00:00:00 2001 From: Jan Blechta Date: Mon, 23 Jul 2018 23:50:39 +0200 Subject: [PATCH 08/10] Fix formatting of real literals --- coffee/base.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/coffee/base.py b/coffee/base.py index a466ca1f..3c76e0be 100644 --- a/coffee/base.py +++ b/coffee/base.py @@ -271,9 +271,11 @@ def _formatter(self, v): elif isnan(v): return "NAN" elif abs(v.real - round(v.real, 1)) < eps and abs(v.imag - round(v.imag, 1)) < eps: - return f_int % v.real + ' + ' + f_int % v.imag + ' * I' + formatter = f_int else: - return f % v.real + ' + ' + f % v.imag + ' * I' + formatter = f + re, im, zero = map(lambda arg: formatter % arg, (v.real, v.imag, 0)) + return re if im == zero else re + ' + ' + im + ' * I' def _tabulate_values(self, arr): if len(arr.shape) == 1: From 585ce6b7c355df02740ac6c9f81794efa5ea6d60 Mon Sep 17 00:00:00 2001 From: David Ham Date: Wed, 3 Oct 2018 14:46:11 +0100 Subject: [PATCH 09/10] remove deprecation warnings --- coffee/visitor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coffee/visitor.py b/coffee/visitor.py index 82e6f027..12ea3bb6 100644 --- a/coffee/visitor.py +++ b/coffee/visitor.py @@ -44,7 +44,7 @@ def __init__(self): # Check the argument specification # Valid options are: # visit_Foo(self, o, [*args, **kwargs]) - argspec = inspect.getargspec(meth) + argspec = inspect.getfullargspec(meth) if len(argspec.args) < 2: raise RuntimeError("Visit method signature must be visit_Foo(self, o, [*args, **kwargs])") handlers[name[len(prefix):]] = meth From f62fcbf8715ddb832d5be604f038fe64e3bbd58f Mon Sep 17 00:00:00 2001 From: David Ham Date: Wed, 3 Oct 2018 14:46:21 +0100 Subject: [PATCH 10/10] Fix docstring --- coffee/base.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/coffee/base.py b/coffee/base.py index 3c76e0be..3bf2f55b 100644 --- a/coffee/base.py +++ b/coffee/base.py @@ -260,9 +260,12 @@ def values(self, val): self._values = val def _formatter(self, v): - """Format a complex into a string, showing up to ``precision`` decimal digits. - This function is partly extracted from the open_source "FFC: the FEniCS Form - Compiler", freely accessible at https://bitbucket.org/fenics-project/ffc.""" + """Format a real or complex value into a string, showing up to + ``precision`` decimal digits. This function is partly + extracted from the open_source "FFC: the FEniCS Form + Compiler", freely accessible at + https://bitbucket.org/fenics-project/ffc. + """ f = "%%.%dg" % self.precision f_int = "%%.%df" % 1 eps = 10.0**(-self.precision)