def _var(arg): if isinstance(arg, Declaration): return arg.variable elif isinstance(arg, Variable): return arg else: return Variable.deduced(arg)
def test_Subroutine(): # Code to generate the subroutine in the example from # http://www.fortran90.org/src/best-practices.html#arrays r = Symbol("r", real=True) i = Symbol("i", integer=True) v_r = Variable.deduced(r, attrs=(dimension(assumed_extent), intent_out)) v_i = Variable.deduced(i) v_n = Variable("n", integer) do_loop = Do([Assignment(Element(r, [i]), literal_dp(1) / i**2)], i, 1, v_n) sub = Subroutine( "f", [v_r], [ Declaration(v_n), Declaration(v_i), Assignment(v_n, size(r)), do_loop ], ) x = Symbol("x", real=True) v_x3 = Variable.deduced(x, attrs=[dimension(3)]) mod = Module("mymod", definitions=[sub]) prog = Program( "foo", [ use(mod, only=[sub]), Declaration(v_x3), SubroutineCall(sub, [v_x3]), Print([sum_(v_x3), v_x3]), ], ) if not has_fortran(): skip("No fortran compiler found.") (stdout, stderr), info = compile_run_strings( [("a.f90", fcode(mod, standard=90)), ("b.f90", fcode(prog, standard=90))], clean=True, ) ref = [1.0 / i**2 for i in range(1, 4)] assert str(sum(ref))[:-3] in stdout for _ in ref: assert str(_)[:-3] in stdout assert stderr == ""
def test_Subroutine(): # Code to generate the subroutine in the example from # http://www.fortran90.org/src/best-practices.html#arrays r = Symbol('r', real=True) i = Symbol('i', integer=True) v_r = Variable.deduced(r, attrs=(dimension(assumed_extent), intent_out)) v_i = Variable.deduced(i) v_n = Variable('n', integer) do_loop = Do([ Assignment(Element(r, [i]), literal_dp(1)/i**2) ], i, 1, v_n) sub = Subroutine("f", [v_r], [ Declaration(v_n), Declaration(v_i), Assignment(v_n, size(r)), do_loop ]) x = Symbol('x', real=True) v_x3 = Variable.deduced(x, attrs=[dimension(3)]) mod = Module('mymod', definitions=[sub]) prog = Program('foo', [ use(mod, only=[sub]), Declaration(v_x3), SubroutineCall(sub, [v_x3]), Print([sum_(v_x3), v_x3]) ]) if not has_fortran(): skip("No fortran compiler found.") (stdout, stderr), info = compile_run_strings([ ('a.f90', fcode(mod, standard=90)), ('b.f90', fcode(prog, standard=90)) ], clean=True) ref = [1.0/i**2 for i in range(1, 4)] assert str(sum(ref))[:-3] in stdout for _ in ref: assert str(_)[:-3] in stdout assert stderr == ''
def test_Program(): x = Symbol('x', real=True) vx = Variable.deduced(x, 42) decl = Declaration(vx) prnt = Print([x, x+1]) prog = Program('foo', [decl, prnt]) if not has_fortran(): skip("No fortran compiler found.") (stdout, stderr), info = compile_run_strings([('main.f90', fcode(prog, standard=90))], clean=True) assert '42' in stdout assert '43' in stdout assert stderr == '' assert info['exit_status'] == os.EX_OK
def array(symbol, dim, intent=None, **kwargs): """ Convenience function for creating a Variable instance for a Fortran array Parameters ========== symbol : symbol dim : Attribute or iterable If dim is an ``Attribute`` it need to have the name 'dimension'. If it is not an ``Attribute``, then it is passsed to :func:`dimension` as ``*dim`` intent : str One of: 'in', 'out', 'inout' or None \\*\\*kwargs: Keyword arguments for ``Variable`` ('type' & 'value') Examples ======== >>> from sympy.printing import fcode >>> from sympy.codegen.ast import integer, real >>> from sympy.codegen.fnodes import array >>> arr = array('a', '*', 'in', type=integer) >>> print(fcode(arr.as_Declaration(), source_format='free', standard=2003)) integer*4, dimension(*), intent(in) :: a >>> x = array('x', [3, ':', ':'], intent='out', type=real) >>> print(fcode(x.as_Declaration(value=1), source_format='free', standard=2003)) real*8, dimension(3, :, :), intent(out) :: x = 1 """ if isinstance(dim, Attribute): if str(dim.name) != 'dimension': raise ValueError( "Got an unexpected Attribute argument as dim: %s" % str(dim)) else: dim = dimension(*dim) attrs = list(kwargs.pop('attrs', [])) + [dim] if intent is not None: if intent not in (intent_in, intent_out, intent_inout): intent = { 'in': intent_in, 'out': intent_out, 'inout': intent_inout }[intent] attrs.append(intent) value = kwargs.pop('value', None) type_ = kwargs.pop('type', None) if type_ is None: return Variable.deduced(symbol, value=value, attrs=attrs) else: return Variable(symbol, type_, value=value, attrs=attrs)
def test_Program(): x = Symbol('x', real=True) vx = Variable.deduced(x, 42) decl = Declaration(vx) prnt = Print([x, x+1]) prog = Program('foo', [decl, prnt]) if not has_fortran(): skip("No fortran compiler found.") (stdout, stderr), info = compile_run_strings([('main.f90', fcode(prog, standard=90))], clean=True) assert '42' in stdout assert '43' in stdout assert stderr == '' assert info['exit_status'] == os.EX_OK
def test_Program(): x = Symbol("x", real=True) vx = Variable.deduced(x, 42) decl = Declaration(vx) prnt = Print([x, x + 1]) prog = Program("foo", [decl, prnt]) if not has_fortran(): skip("No fortran compiler found.") (stdout, stderr), info = compile_run_strings( [("main.f90", fcode(prog, standard=90))], clean=True) assert "42" in stdout assert "43" in stdout assert stderr == "" assert info["exit_status"] == os.EX_OK
def test_Variable(): v = Variable(x, type_=Type('real')) assert v.symbol == x assert v.type == real assert v.value_const == False w = Variable(y, {value_const}, f32) assert w.symbol == y assert w.type == f32 assert w.value_const v_n = Variable(n, type_=Type.from_expr(n)) assert v_n.type == integer v_i = Variable(i, type_=Type.from_expr(n)) assert v_i.type == integer a_i = Variable.deduced(i) assert a_i.type == integer
def array(symbol, dim, intent=None, **kwargs): """ Convenience function for creating a Variable instance for a Fortran array Parameters ========== symbol : symbol dim : Attribute or iterable If dim is an ``Attribute`` it need to have the name 'dimension'. If it is not an ``Attribute``, then it is passsed to :func:`dimension` as ``*dim`` intent : str One of: 'in', 'out', 'inout' or None \\*\\*kwargs: Keyword arguments for ``Variable`` ('type' & 'value') Examples ======== >>> from sympy.printing import fcode >>> from sympy.codegen.ast import integer, real >>> from sympy.codegen.fnodes import array >>> arr = array('a', '*', 'in', type=integer) >>> print(fcode(arr.as_Declaration(), source_format='free', standard=2003)) integer*4, dimension(*), intent(in) :: a >>> x = array('x', [3, ':', ':'], intent='out', type=real) >>> print(fcode(x.as_Declaration(value=1), source_format='free', standard=2003)) real*8, dimension(3, :, :), intent(out) :: x = 1 """ if isinstance(dim, Attribute): if str(dim.name) != 'dimension': raise ValueError("Got an unexpected Attribute argument as dim: %s" % str(dim)) else: dim = dimension(*dim) attrs = list(kwargs.pop('attrs', [])) + [dim] if intent is not None: if intent not in (intent_in, intent_out, intent_inout): intent = {'in': intent_in, 'out': intent_out, 'inout': intent_inout}[intent] attrs.append(intent) value = kwargs.pop('value', None) type_ = kwargs.pop('type', None) if type_ is None: return Variable.deduced(symbol, value=value, attrs=attrs) else: return Variable(symbol, type_, value=value, attrs=attrs)
def test_Module(): x = Symbol('x', real=True) v_x = Variable.deduced(x) sq = FunctionDefinition(real, 'sqr', [v_x], [Return(x**2)]) mod_sq = Module('mod_sq', [], [sq]) sq_call = FunctionCall('sqr', [42.]) prg_sq = Program('foobar', [ use('mod_sq', only=['sqr']), Print(['"Square of 42 = "', sq_call]) ]) if not has_fortran(): skip("No fortran compiler found.") (stdout, stderr), info = compile_run_strings([ ('mod_sq.f90', fcode(mod_sq, standard=90)), ('main.f90', fcode(prg_sq, standard=90)) ], clean=True) assert '42' in stdout assert str(42**2) in stdout assert stderr == ''
def test_Module(): x = Symbol('x', real=True) v_x = Variable.deduced(x) sq = FunctionDefinition(real, 'sqr', [v_x], [Return(x**2)]) mod_sq = Module('mod_sq', [], [sq]) sq_call = FunctionCall('sqr', [42.]) prg_sq = Program( 'foobar', [use('mod_sq', only=['sqr']), Print(['"Square of 42 = "', sq_call])]) if not has_fortran(): skip("No fortran compiler found.") (stdout, stderr), info = compile_run_strings( [('mod_sq.f90', fcode(mod_sq, standard=90)), ('main.f90', fcode(prg_sq, standard=90))], clean=True) assert '42' in stdout assert str(42**2) in stdout assert stderr == ''
def test_Variable(): v = Variable(x, type=real) assert v == Variable(v) assert v == Variable('x', type=real) assert v.symbol == x assert v.type == real assert value_const not in v.attrs assert v.func(*v.args) == v assert str(v) == 'Variable(x, type=real)' w = Variable(y, f32, attrs={value_const}) assert w.symbol == y assert w.type == f32 assert value_const in w.attrs assert w.func(*w.args) == w v_n = Variable(n, type=Type.from_expr(n)) assert v_n.type == integer assert v_n.func(*v_n.args) == v_n v_i = Variable(i, type=Type.from_expr(n)) assert v_i.type == integer assert v_i != v_n a_i = Variable.deduced(i) assert a_i.type == integer assert Variable.deduced(Symbol('x', real=True)).type == real assert a_i.func(*a_i.args) == a_i v_n2 = Variable.deduced(n, value=3.5, cast_check=False) assert v_n2.func(*v_n2.args) == v_n2 assert abs(v_n2.value - 3.5) < 1e-15 raises(ValueError, lambda: Variable.deduced(n, value=3.5, cast_check=True)) v_n3 = Variable.deduced(n) assert v_n3.type == integer assert str(v_n3) == 'Variable(n, type=integer)' assert Variable.deduced(z, value=3).type == integer assert Variable.deduced(z, value=3.0).type == real assert Variable.deduced(z, value=3.0 + 1j).type == complex_
def test_Variable(): v = Variable(x, type=real) assert v == Variable(v) assert v == Variable('x', type=real) assert v.symbol == x assert v.type == real assert value_const not in v.attrs assert v.func(*v.args) == v assert str(v) == 'Variable(x, type=real)' w = Variable(y, f32, attrs={value_const}) assert w.symbol == y assert w.type == f32 assert value_const in w.attrs assert w.func(*w.args) == w v_n = Variable(n, type=Type.from_expr(n)) assert v_n.type == integer assert v_n.func(*v_n.args) == v_n v_i = Variable(i, type=Type.from_expr(n)) assert v_i.type == integer assert v_i != v_n a_i = Variable.deduced(i) assert a_i.type == integer assert Variable.deduced(Symbol('x', real=True)).type == real assert a_i.func(*a_i.args) == a_i v_n2 = Variable.deduced(n, value=3.5, cast_check=False) assert v_n2.func(*v_n2.args) == v_n2 assert abs(v_n2.value - 3.5) < 1e-15 raises(ValueError, lambda: Variable.deduced(n, value=3.5, cast_check=True)) v_n3 = Variable.deduced(n) assert v_n3.type == integer assert str(v_n3) == 'Variable(n, type=integer)' assert Variable.deduced(z, value=3).type == integer assert Variable.deduced(z, value=3.0).type == real assert Variable.deduced(z, value=3.0+1j).type == complex_
def test_fcode_Declaration(): def check(expr, ref, **kwargs): assert fcode(expr, standard=95, source_format='free', **kwargs) == ref i = symbols('i', integer=True) var1 = Variable.deduced(i) dcl1 = Declaration(var1) check(dcl1, "integer*4 :: i") x, y = symbols('x y') var2 = Variable(x, float32, value=42, attrs={value_const}) dcl2b = Declaration(var2) check(dcl2b, 'real*4, parameter :: x = 42') var3 = Variable(y, type=bool_) dcl3 = Declaration(var3) check(dcl3, 'logical :: y') check(float32, "real*4") check(float64, "real*8") check(real, "real*4", type_aliases={real: float32}) check(real, "real*8", type_aliases={real: float64})
def test_Module(): x = Symbol("x", real=True) v_x = Variable.deduced(x) sq = FunctionDefinition(real, "sqr", [v_x], [Return(x**2)]) mod_sq = Module("mod_sq", [], [sq]) sq_call = FunctionCall("sqr", [42.0]) prg_sq = Program( "foobar", [use("mod_sq", only=["sqr"]), Print(['"Square of 42 = "', sq_call])]) if not has_fortran(): skip("No fortran compiler found.") (stdout, stderr), info = compile_run_strings( [ ("mod_sq.f90", fcode(mod_sq, standard=90)), ("main.f90", fcode(prg_sq, standard=90)), ], clean=True, ) assert "42" in stdout assert str(42**2) in stdout assert stderr == ""
def test_fcode_Declaration(): def check(expr, ref, **kwargs): assert fcode(expr, standard=95, source_format='free', **kwargs) == ref i = symbols('i', integer=True) var1 = Variable.deduced(i) dcl1 = Declaration(var1) check(dcl1, "integer*4 :: i") x, y = symbols('x y') var2 = Variable(x, float32, value=42, attrs={value_const}) dcl2b = Declaration(var2) check(dcl2b, 'real*4, parameter :: x = 42') var3 = Variable(y, type=bool_) dcl3 = Declaration(var3) check(dcl3, 'logical :: y') check(float32, "real*4") check(float64, "real*8") check(real, "real*4", type_aliases={real: float32}) check(real, "real*8", type_aliases={real: float64})
def test_Variable__deduced(): v_i = Variable.deduced(i) assert v_i.type == integer
def newtons_method(expr, wrt, atol=1e-12, delta=None, debug=False, itermax=None, counter=None): """ Generates an AST for Newton-Raphson method (a root-finding algorithm). Returns an abstract syntax tree (AST) based on ``sympy.codegen.ast`` for Netwon's method of root-finding. Parameters ========== expr : expression wrt : Symbol With respect to, i.e. what is the variable. atol : number or expr Absolute tolerance (stopping criterion) delta : Symbol Will be a ``Dummy`` if ``None``. debug : bool Whether to print convergence information during iterations itermax : number or expr Maximum number of iterations. counter : Symbol Will be a ``Dummy`` if ``None``. Examples ======== >>> from sympy import symbols, cos >>> from sympy.codegen.ast import Assignment >>> from sympy.codegen.algorithms import newtons_method >>> x, dx, atol = symbols('x dx atol') >>> expr = cos(x) - x**3 >>> algo = newtons_method(expr, x, atol, dx) >>> algo.has(Assignment(dx, -expr/expr.diff(x))) True References ========== .. [1] https://en.wikipedia.org/wiki/Newton%27s_method """ if delta is None: delta = Dummy() Wrapper = Scope name_d = 'delta' else: Wrapper = lambda x: x name_d = delta.name delta_expr = -expr / expr.diff(wrt) whl_bdy = [ Assignment(delta, delta_expr), AddAugmentedAssignment(wrt, delta) ] if debug: prnt = Print([wrt, delta], r"{}=%12.5g {}=%12.5g\n".format(wrt.name, name_d)) whl_bdy = [whl_bdy[0], prnt] + whl_bdy[1:] req = Gt(Abs(delta), atol) declars = [Declaration(Variable(delta, type=real, value=oo))] if itermax is not None: counter = counter or Dummy(integer=True) v_counter = Variable.deduced(counter, 0) declars.append(Declaration(v_counter)) whl_bdy.append(AddAugmentedAssignment(counter, 1)) req = And(req, Lt(counter, itermax)) whl = While(req, CodeBlock(*whl_bdy)) blck = declars + [whl] return Wrapper(CodeBlock(*blck))
def newtons_method(expr, wrt, atol=1e-12, delta=None, debug=False, itermax=None, counter=None): """ Generates an AST for Newton-Raphson method (a root-finding algorithm). Returns an abstract syntax tree (AST) based on ``sympy.codegen.ast`` for Netwon's method of root-finding. Parameters ========== expr : expression wrt : Symbol With respect to, i.e. what is the variable. atol : number or expr Absolute tolerance (stopping criterion) delta : Symbol Will be a ``Dummy`` if ``None``. debug : bool Whether to print convergence information during iterations itermax : number or expr Maximum number of iterations. counter : Symbol Will be a ``Dummy`` if ``None``. Examples ======== >>> from sympy import symbols, cos >>> from sympy.codegen.ast import Assignment >>> from sympy.codegen.algorithms import newtons_method >>> x, dx, atol = symbols('x dx atol') >>> expr = cos(x) - x**3 >>> algo = newtons_method(expr, x, atol, dx) >>> algo.has(Assignment(dx, -expr/expr.diff(x))) True References ========== .. [1] https://en.wikipedia.org/wiki/Newton%27s_method """ if delta is None: delta = Dummy() Wrapper = Scope name_d = 'delta' else: Wrapper = lambda x: x name_d = delta.name delta_expr = -expr/expr.diff(wrt) whl_bdy = [Assignment(delta, delta_expr), AddAugmentedAssignment(wrt, delta)] if debug: prnt = Print([wrt, delta], r"{0}=%12.5g {1}=%12.5g\n".format(wrt.name, name_d)) whl_bdy = [whl_bdy[0], prnt] + whl_bdy[1:] req = Gt(Abs(delta), atol) declars = [Declaration(Variable(delta, type=real, value=oo))] if itermax is not None: counter = counter or Dummy(integer=True) v_counter = Variable.deduced(counter, 0) declars.append(Declaration(v_counter)) whl_bdy.append(AddAugmentedAssignment(counter, 1)) req = And(req, Lt(counter, itermax)) whl = While(req, CodeBlock(*whl_bdy)) blck = declars + [whl] return Wrapper(CodeBlock(*blck))