text: import os
  from sympy import Symbol, symbols
  from sympy.codegen.ast import (
      Assignment, Print, Declaration, FunctionDefinition, Return, real,
      FunctionCall, Variable, Element, integer
  )
  from sympy.codegen.fnodes import (
      allocatable, ArrayConstructor, isign, dsign, cmplx, kind, literal_dp,
      Program, Module, use, Subroutine, dimension, assumed_extent, ImpliedDoLoop,
      intent_out, size, Do, SubroutineCall, sum_, array, bind_C
  )
  from sympy.codegen.futils import render_as_module
  from sympy.core.expr import unchanged
  from sympy.core.compatibility import PY3
  from sympy.external import import_module
  from sympy.printing.fcode import fcode
  from sympy.utilities._compilation import has_fortran, compile_run_strings, compile_link_import_strings
  from sympy.utilities._compilation.util import TemporaryDirectory, may_xfail
  from sympy.utilities.pytest import skip
  
  cython = import_module('cython')
  np = import_module('numpy')
  
  
  def test_size():
      x = Symbol('x', real=True)
      sx = size(x)
      assert fcode(sx, source_format='free') == 'size(x)'
  
  
  @may_xfail
  def test_size_assumed_shape():
      if not has_fortran():
          skip("No fortran compiler found.")
      a = Symbol('a', real=True)
      body = [Return((sum_(a**2)/size(a))**.5)]
      arr = array(a, dim=[':'], intent='in')
      fd = FunctionDefinition(real, 'rms', [arr], body)
      render_as_module([fd], 'mod_rms')
  
      (stdout, stderr), info = compile_run_strings([
          ('rms.f90', render_as_module([fd], 'mod_rms')),
          ('main.f90', (
              'program myprog\n'
              'use mod_rms, only: rms\n'
              'real*8, dimension(4), parameter :: x = [4, 2, 2, 2]\n'
              'print *, dsqrt(7d0) - rms(x)\n'
              'end program\n'
          ))
      ], clean=True)
      assert '0.00000' in stdout
      assert stderr == ''
      assert info['exit_status'] == os.EX_OK
  
  
  @may_xfail
  def test_ImpliedDoLoop():
      if not has_fortran():
          skip("No fortran compiler found.")
  
      a, i = symbols('a i', integer=True)
      idl = ImpliedDoLoop(i**3, i, -3, 3, 2)
      ac = ArrayConstructor([-28, idl, 28])
      a = array(a, dim=[':'], attrs=[allocatable])
      prog = Program('idlprog', [
          a.as_Declaration(),
          Assignment(a, ac),
          Print([a])
      ])
      fsrc = fcode(prog, standard=2003, source_format='free')
      (stdout, stderr), info = compile_run_strings([('main.f90', fsrc)], clean=True)
      for numstr in '-28 -27 -1 1 27 28'.split():
          assert numstr in stdout
      assert stderr == ''
      assert info['exit_status'] == os.EX_OK
  
  
  @may_xfail
  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
  
  
  @may_xfail
  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 == ''
  
  
  @may_xfail
  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_isign():
      x = Symbol('x', integer=True)
      assert unchanged(isign, 1, x)
      assert fcode(isign(1, x), standard=95, source_format='free') == 'isign(1, x)'
  
  
  def test_dsign():
      x = Symbol('x')
      assert unchanged(dsign, 1, x)
      assert fcode(dsign(literal_dp(1), x), standard=95, source_format='free') == 'dsign(1d0, x)'
  
  
  def test_cmplx():
      x = Symbol('x')
      assert unchanged(cmplx, 1, x)
  
  
  def test_kind():
      x = Symbol('x')
      assert unchanged(kind, x)
  
  
  def test_literal_dp():
      assert fcode(literal_dp(0), source_format='free') == '0d0'
  
  
  @may_xfail
  def test_bind_C():
      if not has_fortran():
          skip("No fortran compiler found.")
      if not cython:
          skip("Cython not found.")
      if not np:
          skip("NumPy not found.")
  
      a = Symbol('a', real=True)
      s = Symbol('s', integer=True)
      body = [Return((sum_(a**2)/s)**.5)]
      arr = array(a, dim=[s], intent='in')
      fd = FunctionDefinition(real, 'rms', [arr, s], body, attrs=[bind_C('rms')])
      f_mod = render_as_module([fd], 'mod_rms')
  
      with TemporaryDirectory() as folder:
          mod, info = compile_link_import_strings([
              ('rms.f90', f_mod),
              ('_rms.pyx', (
                  "#cython: language_level={}\n".format("3" if PY3 else "2") +
                  "cdef extern double rms(double*, int*)\n"
                  "def py_rms(double[::1] x):\n"
                  "    cdef int s = x.size\n"
                  "    return rms(&x[0], &s)\n"))
          ], build_dir=folder)
          assert abs(mod.py_rms(np.array([2., 4., 2., 2.])) - 7**0.5) < 1e-14
  