---
 doc/src/modules/printing.txt       |   96 +++++++++++
 sympy/__init__.py                  |    2 +-
 sympy/printing/__init__.py         |    1 +
 sympy/printing/fcode.py            |  326 ++++++++++++++++++++++++++++++++++++
 sympy/printing/tests/test_fcode.py |  217 ++++++++++++++++++++++++
 5 files changed, 641 insertions(+), 1 deletions(-)
 create mode 100644 sympy/printing/fcode.py
 create mode 100644 sympy/printing/tests/test_fcode.py

diff --git a/doc/src/modules/printing.txt b/doc/src/modules/printing.txt
index d6178e3..d6714f0 100644
--- a/doc/src/modules/printing.txt
+++ b/doc/src/modules/printing.txt
@@ -84,6 +84,102 @@ This class implements Python printing. Usage::
     x = Symbol('x')
     e = sin(x) + 5*x**3
 
+fcode
+-----
+
+The fcode function translates a sympy expression into Fortran code. The main
+purpose is to take away the burden of manually translating long mathematical
+expressions. Therefore the resulting expression should also require no (or very
+little) manual tweaking to make it compilable. The optional arguments of fcode
+can be used to fine-tune the behavior of fcode in such a way that manual 
changes
+in the result are no longer needed.
+
+.. module:: sympy.printing.fcode
+.. autofunction:: fcode
+.. autofunction:: print_fcode
+
+Two basic examples:
+
+    >>> from sympy import *
+    >>> x = symbols("x")
+    >>> fcode(sqrt(1-x**2))
+    '      sqrt(1 - x**2)'
+    >>> fcode((3 + 4*I)/(1 - conjugate(x)))
+    '      (cmplx(3,4))/(1 - conjg(x))'
+
+An example where line wrapping is required:
+
+    >>> expr = sqrt(1-x**2).series(x,n=20).removeO()
+    >>> print fcode(expr)
+          1 - x**2/2 - x**4/8 - x**6/16 - 5*x**8/128 - 7*x**10/256 - 21*x
+         @ **12/1024 - 33*x**14/2048 - 429*x**16/32768 - 715*x**18/65536
+
+In case of line wrapping, it is handy to include the assignment so that lines
+are wrapped properly when the assignment part is added.
+
+    >>> print fcode(expr, assign_to="var")
+          var = 1 - x**2/2 - x**4/8 - x**6/16 - 5*x**8/128 - 7*x**10/256 -
+         @ 21*x**12/1024 - 33*x**14/2048 - 429*x**16/32768 - 715*x**18/65536
+
+Also for piecewise functions, the assign_to option can be helpful:
+
+    >>> print fcode(Piecewise((x,x<1),(x**2,True)), assign_to="var")
+          if (x < 1) then
+            var = x
+          else
+            var = x**2
+          end if
+
+Note that only top-level piecewise functions are supported due to the lack of
+a conditional operator in Fortran. Nested piecewise functions would require the
+introduction of temporary variables, which is a type of expression manipulation
+that goes beyond the scope of fcode.
+
+By default, number symbols such as ``pi`` and ``E`` are detected and defined as
+Fortran parameters. The precision of the constants can be tuned with the
+precision argument. Parameter definitions are easily avoided using the ``N``
+function.
+
+    >>> print fcode(x - pi**2 - E)
+          parameter (E = 2.71828182845905)
+          parameter (pi = 3.14159265358979)
+          x - E - pi**2
+    >>> print fcode(x - pi**2 - E, precision=25)
+          parameter (E = 2.718281828459045235360287)
+          parameter (pi = 3.141592653589793238462643)
+          x - E - pi**2
+    >>> print fcode(N(x - pi**2, 25))
+          -9.869604401089358618834491 + x
+
+When some functions are not part of the Fortran standard, it might be desirable
+to introduce the names of user-defined functions in the Fortran expression.
+
+    >>> print fcode(1 - gamma(x)**2, user_functions={gamma: 'mygamma'})
+          1 - mygamma(x)**2
+
+However, when the user_functions argument is not provided, fcode attempts to
+use a reasonable default and adds a comment to inform the user of the issue.
+
+    >>> print fcode(1 - gamma(x)**2)
+    C     Not Fortran 77:
+    C     gamma(x)
+          1 - gamma(x)**2
+
+By default the output is human readable code, ready for copy and paste. With 
the
+option ``human=False``, the return value is suitable for post-processing with
+source code generators that write routines with multiple instructions. The
+return value is a three-tuple containing: (i) the list of number symbols that
+must be defined as 'Fortran parameters', (ii) a list functions that can not be
+translated in pure Fortran and (iii) a string of Fortran code. A few examples:
+
+    >>> fcode(1 - gamma(x)**2, human=False)
+    ([], set([gamma(x)]), '      1 - gamma(x)**2')
+    >>> fcode(1 - sin(x)**2, human=False)
+    ([], set(), '      1 - sin(x)**2')
+    >>> fcode(x - pi**2, human=False)
+    ([('pi', 3.14159265358979)], set(), '      x - pi**2')
+
+
 Preview
 -------
 
diff --git a/sympy/__init__.py b/sympy/__init__.py
index 2cc73f8..81cd4a5 100644
--- a/sympy/__init__.py
+++ b/sympy/__init__.py
@@ -38,7 +38,7 @@ def __sympy_debug():
 from plotting import Plot, textplot
 from printing import pretty, pretty_print, pprint, pprint_use_unicode, \
     pprint_try_use_unicode, print_gtk, print_tree
-from printing import ccode, latex, preview
+from printing import ccode, fcode, latex, preview
 from printing import python, print_python, srepr, sstr, sstrrepr
 
 evalf._create_evalf_table()
diff --git a/sympy/printing/__init__.py b/sympy/printing/__init__.py
index 1ade76d..40065a0 100644
--- a/sympy/printing/__init__.py
+++ b/sympy/printing/__init__.py
@@ -5,6 +5,7 @@
 from mathml import mathml, print_mathml
 from python import python, print_python
 from ccode import ccode, print_ccode
+from fcode import fcode, print_fcode
 from gtk import *
 
 from preview import preview
diff --git a/sympy/printing/fcode.py b/sympy/printing/fcode.py
new file mode 100644
index 0000000..6211920
--- /dev/null
+++ b/sympy/printing/fcode.py
@@ -0,0 +1,326 @@
+"""
+Fortran code printer
+
+The FCodePrinter converts single sympy expressions into single Fortran
+expressions, using the functions defined in the Fortran 77 standard where
+possible. Some useful pointers to Fortran can be found on wikipedia:
+
+http://en.wikipedia.org/wiki/Fortran
+
+Most of the code below is based on the "Professional Programmer\'s Guide to
+Fortran77" by Clive G. Page:
+
+http://www.star.le.ac.uk/~cgp/prof77.html
+
+Fortran is a case-insensitive language. This might cause trouble because sympy
+is case sensitive. The implementation below does not care and leaves the
+responsibility for generating properly cased Fortran code to the user.
+"""
+
+
+from str import StrPrinter
+from sympy.printing.precedence import precedence
+from sympy.core import S, Add, I
+from sympy.core.numbers import NumberSymbol
+from sympy.functions import sin, cos, tan, asin, acos, atan, atan2, sinh, \
+    cosh, tanh, sqrt, log, exp, abs, sign, conjugate, Piecewise
+from sympy.utilities.iterables import postorder_traversal
+
+
+implicit_functions = set([
+    sin, cos, tan, asin, acos, atan, atan2, sinh, cosh, tanh, sqrt, log, exp,
+    abs, sign, conjugate
+])
+
+
+class FCodePrinter(StrPrinter):
+    """A printer to convert sympy expressions to strings of Fortran code"""
+    printmethod = "_fcode_"
+
+    def doprint(self, expr):
+        """Returns Fortran code for expr (as a string)"""
+        # keep a set of expressions that are not strictly translatable to
+        # Fortran.
+        self.not_fortran = set([])
+
+        lines = []
+        if isinstance(expr, Piecewise):
+            # support for top-level Piecewise function
+            for i, (e, c) in enumerate(expr.args):
+                if i == 0:
+                    lines.append("      if (%s) then" % self._print(c))
+                elif i == len(expr.args)-1 and c == True:
+                    lines.append("      else")
+                else:
+                    lines.append("      else if (%s) then" % self._print(c))
+                if self._settings["assign_to"] is None:
+                    lines.append("        %s" % self._print(e))
+                else:
+                    lines.append("        %s = %s" % 
(self._settings["assign_to"], self._print(e)))
+            lines.append("      end if")
+            return "\n".join(lines)
+        else:
+            line = StrPrinter.doprint(self, expr)
+            if self._settings["assign_to"] is None:
+                return "      %s" % line
+            else:
+                return "      %s = %s" % (self._settings["assign_to"], line)
+
+    def _print_Add(self, expr):
+        # purpose: print complex numbers nicely in Fortran.
+        # collect the purely real and purely imaginary parts:
+        pure_real = []
+        pure_imaginary = []
+        mixed = []
+        for arg in expr.args:
+            if arg.is_real and arg.is_number:
+                pure_real.append(arg)
+            elif arg.is_imaginary and arg.is_number:
+                pure_imaginary.append(arg)
+            else:
+                mixed.append(arg)
+        if len(pure_imaginary) > 0:
+            if len(mixed) > 0:
+                PREC = precedence(expr)
+                term = Add(*mixed)
+                t = self._print(term)
+                if t.startswith('-'):
+                    sign = "-"
+                    t = t[1:]
+                else:
+                    sign = "+"
+                if precedence(term) < PREC:
+                    t = "(%s)" % t
+
+                return "cmplx(%s,%s) %s %s" % (
+                    self._print(Add(*pure_real)),
+                    self._print(-I*Add(*pure_imaginary)),
+                    sign, t,
+                )
+            else:
+                return "cmplx(%s,%s)" % (
+                    self._print(Add(*pure_real)),
+                    self._print(-I*Add(*pure_imaginary)),
+                )
+        else:
+            return StrPrinter._print_Add(self, expr)
+
+    def _print_Function(self, expr):
+        name = self._settings["user_functions"].get(expr.__class__)
+        if name is None:
+            if expr.func == conjugate:
+                name = "conjg"
+            else:
+                name = expr.func.__name__
+            if expr.func not in implicit_functions:
+                self.not_fortran.add(expr)
+        return "%s(%s)" % (name, self.stringify(expr.args, ", "))
+
+    _print_Factorial = _print_Function
+
+    def _print_ImaginaryUnit(self, expr):
+        # purpose: print complex numbers nicely in Fortran.
+        return "cmplx(0,1)"
+
+    def _print_int(self, expr):
+        return str(expr)
+
+    def _print_Mul(self, expr):
+        # purpose: print complex numbers nicely in Fortran.
+        if expr.is_imaginary and expr.is_number:
+            return "cmplx(0,%s)" % (
+                self._print(-I*expr)
+            )
+        else:
+            return StrPrinter._print_Mul(self, expr)
+
+    def _print_NumberSymbol(self, expr):
+        # Standard Fortran has no predefined constants. Write their string
+        # representation, and assume parameter statements are defined elsewhere
+        # in the code to make this work.
+        return str(expr)
+
+    _print_Catalan = _print_NumberSymbol
+    _print_EulerGamma = _print_NumberSymbol
+    _print_Exp1 = _print_NumberSymbol
+    _print_GoldenRatio = _print_NumberSymbol
+    _print_Pi = _print_NumberSymbol
+
+    def _print_Pow(self, expr):
+        PREC = precedence(expr)
+        if expr.exp is S.NegativeOne:
+            return '1.0/%s'%(self.parenthesize(expr.base, PREC))
+        elif expr.exp == 0.5:
+            return 'sqrt(%s)' % self._print(expr.base)
+        else:
+            return StrPrinter._print_Pow(self, expr)
+
+    def _print_Rational(self, expr):
+        p, q = int(expr.p), int(expr.q)
+        return '%d.0/%d.0' % (p, q)
+
+    def _print_not_fortran(self, expr):
+        self.not_fortran.add(expr)
+        return StrPrinter.emptyPrinter(self, expr)
+
+    # The following can not be simply translated into Fortran.
+    _print_Basic = _print_not_fortran
+    _print_ComplexInfinity = _print_not_fortran
+    _print_Derivative = _print_not_fortran
+    _print_dict = _print_not_fortran
+    _print_Dummy = _print_not_fortran
+    _print_ExprCondPair = _print_not_fortran
+    _print_GeometryEntity = _print_not_fortran
+    _print_Infinity = _print_not_fortran
+    _print_Integral = _print_not_fortran
+    _print_Interval = _print_not_fortran
+    _print_Limit = _print_not_fortran
+    _print_list = _print_not_fortran
+    _print_Matrix = _print_not_fortran
+    _print_DeferredVector = _print_not_fortran
+    _print_NaN = _print_not_fortran
+    _print_NegativeInfinity = _print_not_fortran
+    _print_Normal = _print_not_fortran
+    _print_Order = _print_not_fortran
+    _print_PDF = _print_not_fortran
+    _print_RootOf = _print_not_fortran
+    _print_RootsOf = _print_not_fortran
+    _print_RootSum = _print_not_fortran
+    _print_Sample = _print_not_fortran
+    _print_SMatrix = _print_not_fortran
+    _print_tuple = _print_not_fortran
+    _print_Uniform = _print_not_fortran
+    _print_Unit = _print_not_fortran
+    _print_Wild = _print_not_fortran
+    _print_WildFunction = _print_not_fortran
+
+
+def wrap_fortran(lines):
+    """Wrap long Fortran lines
+
+       Argument:
+         lines  --  a list of lines (without \\n character)
+
+       A comment line is split at white space. Code lines are split with a more
+       complex rule to give nice results.
+    """
+    # routine to find split point in a code line
+    my_alnum = set("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_")
+    my_white = set(" \t()")
+    def split_pos_code(line, endpos):
+        if len(line) <= endpos:
+            return len(line)
+        pos = endpos
+        split = lambda pos: \
+            (line[pos] in my_alnum and line[pos-1] not in my_alnum) or \
+            (line[pos] not in my_alnum and line[pos-1] in my_alnum) or \
+            (line[pos] in my_white and line[pos-1] not in my_white) or \
+            (line[pos] not in my_white and line[pos-1] in my_white)
+        while not split(pos):
+            pos -= 1
+            if pos == 0:
+                return endpos
+        return pos
+    # split line by line and add the splitted lines to result
+    result = []
+    for line in lines:
+        if line.startswith("      "):
+            # code line
+            pos = split_pos_code(line, 72)
+            hunk = line[:pos].rstrip()
+            line = line[pos:].lstrip()
+            result.append(hunk)
+            while len(line) > 0:
+                pos = split_pos_code(line, 65)
+                hunk = line[:pos].rstrip()
+                line = line[pos:].lstrip()
+                result.append("     @ %s" % hunk)
+        elif line.startswith("C"):
+            # comment line
+            if len(line) > 72:
+                pos = line.rfind(" ", 6, 72)
+                if pos == -1:
+                    pos = 72
+                hunk = line[:pos]
+                line = line[pos:].lstrip()
+                result.append(hunk)
+                while len(line) > 0:
+                    pos = line.rfind(" ", 0, 66)
+                    if pos == -1:
+                        pos = 66
+                    hunk = line[:pos]
+                    line = line[pos:].lstrip()
+                    result.append("C     %s" % hunk)
+            else:
+                result.append(line)
+        else:
+            result.append(line)
+    return result
+
+
+def fcode(expr, assign_to=None, precision=15, user_functions={}, human=True):
+    """Converts an expr to a string of Fortran 77 code
+
+       Arguments:
+         expr  --  a sympy expression to be converted
+
+       Optional arguments:
+         assign_to  --  When given, the argument is used as the name of the
+                        variable to which the Fortran expression is assigned.
+                        (This is helpful in case of line-wrapping.)
+         precision  --  the precision for numbers such as pi [default=15]
+         user_functions  --  A dictionary where keys are FunctionClass 
instances
+                             and values are there string representations.
+         human  --  If True, the result is a single string that may contain
+                    some parameter statements for the number symbols. If
+                    False, the same information is returned in a more
+                    programmer-friendly data structure.
+
+       >>> from sympy import fcode, symbols, Rational, pi, sin
+       >>> x, tau = symbols(["x", "tau"])
+       >>> fcode((2*tau)**Rational(7,2))
+       '      8*sqrt(2)*tau**(7.0/2.0)'
+       >>> fcode(sin(x), assign_to="s")
+       '      s = sin(x)'
+       >>> print fcode(pi)
+             parameter (pi = 3.14159265358979)
+             pi
+
+    """
+    # find all number symbols
+    number_symbols = set([])
+    for sub in postorder_traversal(expr):
+        if isinstance(sub, NumberSymbol):
+            number_symbols.add(sub)
+    number_symbols = [(str(ns), ns.evalf(precision)) for ns in 
sorted(number_symbols)]
+    # run the printer
+    profile = {
+        "full_prec": False, # programmers don't care about trailing zeros.
+        "assign_to": assign_to,
+        "user_functions": user_functions,
+    }
+    printer = FCodePrinter(profile)
+    result = printer.doprint(expr)
+    # format the output
+    if human:
+        lines = []
+        if len(printer.not_fortran) > 0:
+            lines.append("C     Not Fortran 77:")
+            for expr in sorted(printer.not_fortran):
+                lines.append("C     %s" % expr)
+        for name, value in number_symbols:
+            lines.append("      parameter (%s = %s)" % (name, value))
+        lines.extend(result.split("\n"))
+        lines = wrap_fortran(lines)
+        return "\n".join(lines)
+    else:
+        return number_symbols, printer.not_fortran, result
+
+
+def print_fcode(expr, assign_to=None, precision=15, user_functions={}):
+    """Prints the Fortran representation of the given expression.
+
+       See fcode for the meaning of the optional arguments.
+    """
+    print fcode(expr, assign_to, precision, user_functions)
+
diff --git a/sympy/printing/tests/test_fcode.py 
b/sympy/printing/tests/test_fcode.py
new file mode 100644
index 0000000..44cb24c
--- /dev/null
+++ b/sympy/printing/tests/test_fcode.py
@@ -0,0 +1,217 @@
+from sympy import sin, cos, atan2, gamma, conjugate, sqrt, Factorial, \
+    Integral, Piecewise, Add, diff, symbols, raises
+from sympy import Catalan, EulerGamma, E, GoldenRatio, I, pi
+from sympy import Function, Rational, Integer
+
+from sympy.printing.fcode import fcode, wrap_fortran
+
+
+def test_printmethod():
+    x = symbols('x')
+    class nint(Function):
+        def _fcode_(self, printer):
+            return "nint(%s)" % printer._print(self.args[0])
+    assert fcode(nint(x)) == "      nint(x)"
+
+def test_fcode_Pow():
+    x, y = symbols('xy')
+    assert fcode(x**3) == "      x**3"
+    assert fcode(x**(y**3)) == "      x**(y**3)"
+    assert fcode(1/(sin(x)*3.5)**(x - y**x)/(x**2 + y)) == \
+        "      (3.5*sin(x))**(-x + y**x)/(y + x**2)"
+    assert fcode(sqrt(x)) == '      sqrt(x)'
+    assert fcode(x**0.5) == '      sqrt(x)'
+    assert fcode(x**Rational(1,2)) == '      sqrt(x)'
+
+def test_fcode_Rational():
+    assert fcode(Rational(3,7)) == "      3.0/7.0"
+    assert fcode(Rational(18,9)) == "      2"
+    assert fcode(Rational(3,-7)) == "      -3.0/7.0"
+    assert fcode(Rational(-3,-7)) == "      3.0/7.0"
+
+def test_fcode_Integer():
+    assert fcode(Integer(67)) == "      67"
+    assert fcode(Integer(-1)) == "      -1"
+
+def test_fcode_functions():
+    x, y = symbols('xy')
+    assert fcode(sin(x) ** cos(y)) == "      sin(x)**cos(y)"
+
+def test_fcode_NumberSymbol():
+    assert fcode(Catalan) == '      parameter (Catalan = 0.915965594177219)\n  
    Catalan'
+    assert fcode(EulerGamma) == '      parameter (EulerGamma = 
0.577215664901533)\n      EulerGamma'
+    assert fcode(E) == '      parameter (E = 2.71828182845905)\n      E'
+    assert fcode(GoldenRatio) == '      parameter (GoldenRatio = 
1.61803398874989)\n      GoldenRatio'
+    assert fcode(pi) == '      parameter (pi = 3.14159265358979)\n      pi'
+    assert fcode(pi,precision=5) == '      parameter (pi = 3.1416)\n      pi'
+    assert fcode(Catalan,human=False) == ([('Catalan', Catalan.evalf(15))], 
set([]), '      Catalan')
+    assert fcode(EulerGamma,human=False) == ([('EulerGamma', 
EulerGamma.evalf(15))], set([]), '      EulerGamma')
+    assert fcode(E,human=False) == ([('E', E.evalf(15))], set([]), '      E')
+    assert fcode(GoldenRatio,human=False) == ([('GoldenRatio', 
GoldenRatio.evalf(15))], set([]), '      GoldenRatio')
+    assert fcode(pi,human=False) == ([('pi', pi.evalf(15))], set([]), '      
pi')
+    assert fcode(pi,precision=5,human=False) == ([('pi', pi.evalf(5))], 
set([]), '      pi')
+
+def test_fcode_complex():
+    assert fcode(I) == "      cmplx(0,1)"
+    x = symbols('x')
+    assert fcode(4*I) == "      cmplx(0,4)"
+    assert fcode(3+4*I) == "      cmplx(3,4)"
+    assert fcode(3+4*I+x) == "      cmplx(3,4) + x"
+    assert fcode(I*x) == "      cmplx(0,1)*x"
+    assert fcode(3+4*I-x) == "      cmplx(3,4) - x"
+    x = symbols('x', imaginary=True)
+    assert fcode(5*x) == "      5*x"
+    assert fcode(I*x) == "      cmplx(0,1)*x"
+    assert fcode(3+x) == "      3 + x"
+
+def test_implicit():
+    x, y = symbols('xy')
+    assert fcode(sin(x)) == "      sin(x)"
+    assert fcode(atan2(x,y)) == "      atan2(x, y)"
+    assert fcode(conjugate(x)) == "      conjg(x)"
+
+def test_not_fortran():
+    x = symbols('x')
+    g = Function('g')
+    assert fcode(gamma(x)) == "C     Not Fortran 77:\nC     gamma(x)\n      
gamma(x)"
+    assert fcode(Integral(sin(x))) == "C     Not Fortran 77:\nC     
Integral(sin(x), x)\n      Integral(sin(x), x)"
+    assert fcode(g(x)) == "C     Not Fortran 77:\nC     g(x)\n      g(x)"
+
+def test_user_functions():
+    x = symbols('x')
+    assert fcode(sin(x), user_functions={sin: "zsin"}) == "      zsin(x)"
+    x = symbols('x')
+    assert fcode(gamma(x), user_functions={gamma: "mygamma"}) == "      
mygamma(x)"
+    g = Function('g')
+    assert fcode(g(x), user_functions={g: "great"}) == "      great(x)"
+    n = symbols('n', integer=True)
+    assert fcode(Factorial(n), user_functions={Factorial: "fct"}) == "      
fct(n)"
+
+def test_assign_to():
+    x = symbols('x')
+    assert fcode(sin(x), assign_to="s") == "      s = sin(x)"
+
+def test_line_wrapping():
+    x, y = symbols('xy')
+    assert fcode(((x+y)**10).expand(), assign_to="var") == (
+        "      var = 45*x**8*y**2 + 120*x**7*y**3 + 210*x**6*y**4 + 
252*x**5*y**5\n"
+        "     @ + 210*x**4*y**6 + 120*x**3*y**7 + 45*x**2*y**8 + 10*x*y**9 + 
10*y\n"
+        "     @ *x**9 + x**10 + y**10"
+    )
+    e = [x**i for i in range(11)]
+    assert fcode(Add(*e)) == (
+        "      1 + x + x**2 + x**3 + x**4 + x**5 + x**6 + x**7 + x**8 + x**9 + 
x\n"
+        "     @ **10"
+    )
+
+def test_fcode_Piecewise():
+    x = symbols('x')
+    assert fcode(Piecewise((x,x<1),(x**2,True))) == (
+        "      if (x < 1) then\n"
+        "        x\n"
+        "      else\n"
+        "        x**2\n"
+        "      end if"
+    )
+    assert fcode(Piecewise((x,x<1),(x**2,True)), assign_to="var") == (
+        "      if (x < 1) then\n"
+        "        var = x\n"
+        "      else\n"
+        "        var = x**2\n"
+        "      end if"
+    )
+    a = cos(x)/x
+    b = sin(x)/x
+    for i in xrange(10):
+        a = diff(a, x)
+        b = diff(b, x)
+    assert fcode(Piecewise((a,x<0),(b,True)), assign_to="weird_name") == (
+        "      if (x < 0) then\n"
+        "        weird_name = -cos(x)/x - 1814400*cos(x)/x**9 - 
604800*sin(x)/x\n"
+        "     @ **8 - 5040*cos(x)/x**5 - 720*sin(x)/x**4 + 10*sin(x)/x**2 + 
90*\n"
+        "     @ cos(x)/x**3 + 30240*sin(x)/x**6 + 151200*cos(x)/x**7 + 
3628800*\n"
+        "     @ cos(x)/x**11 + 3628800*sin(x)/x**10\n"
+        "      else\n"
+        "        weird_name = -sin(x)/x - 3628800*cos(x)/x**10 - 
1814400*sin(x)/x\n"
+        "     @ **9 - 30240*cos(x)/x**6 - 5040*sin(x)/x**5 - 10*cos(x)/x**2 + 
90*\n"
+        "     @ sin(x)/x**3 + 720*cos(x)/x**4 + 151200*sin(x)/x**7 + 
604800*cos(x\n"
+        "     @ )/x**8 + 3628800*sin(x)/x**11\n"
+        "      end if"
+    )
+    assert fcode(Piecewise((x,x<1),(x**2,x>1),(sin(x),True))) == (
+        "      if (x < 1) then\n"
+        "        x\n"
+        "      else if (1 < x) then\n"
+        "        x**2\n"
+        "      else\n"
+        "        sin(x)\n"
+        "      end if"
+    )
+    assert fcode(Piecewise((x,x<1),(x**2,x>1),(sin(x),x>0))) == (
+        "      if (x < 1) then\n"
+        "        x\n"
+        "      else if (1 < x) then\n"
+        "        x**2\n"
+        "      else if (0 < x) then\n"
+        "        sin(x)\n"
+        "      end if"
+    )
+
+def test_wrap_fortran():
+    #   
"########################################################################"
+    lines = [
+        "C     This is a long comment on a single line that must be wrapped 
properly",
+        "      this = is + a + long + and + nasty + fortran + statement + that 
* must + be + wrapped + properly",
+        "      this = is + a + long + and + nasty + fortran + statement +  
that * must + be + wrapped + properly",
+        "      this = is + a + long + and + nasty + fortran + statement +   
that * must + be + wrapped + properly",
+        "      this = is + a + long + and + nasty + fortran + statement + 
that*must + be + wrapped + properly",
+        "      this = is + a + long + and + nasty + fortran + statement +   
that*must + be + wrapped + properly",
+        "      this = is + a + long + and + nasty + fortran + statement +    
that*must + be + wrapped + properly",
+        "      this = is + a + long + and + nasty + fortran + statement +     
that*must + be + wrapped + properly",
+        "      this = is + a + long + and + nasty + fortran + statement + 
that**must + be + wrapped + properly",
+        "      this = is + a + long + and + nasty + fortran + statement +  
that**must + be + wrapped + properly",
+        "      this = is + a + long + and + nasty + fortran + statement +   
that**must + be + wrapped + properly",
+        "      this = is + a + long + and + nasty + fortran + statement +    
that**must + be + wrapped + properly",
+        "      this = is + a + long + and + nasty + fortran + statement +     
that**must + be + wrapped + properly",
+        "      this = is + a + long + and + nasty + fortran + 
statement(that)/must + be + wrapped + properly",
+        "      this = is + a + long + and + nasty + fortran +     
statement(that)/must + be + wrapped + properly",
+    ]
+    wrapped_lines = wrap_fortran(lines)
+    expected_lines = [
+        "C     This is a long comment on a single line that must be wrapped",
+        "C     properly",
+        "      this = is + a + long + and + nasty + fortran + statement + that 
*",
+        "     @ must + be + wrapped + properly",
+        "      this = is + a + long + and + nasty + fortran + statement +  
that *",
+        "     @ must + be + wrapped + properly",
+        "      this = is + a + long + and + nasty + fortran + statement +   
that",
+        "     @ * must + be + wrapped + properly",
+        "      this = is + a + long + and + nasty + fortran + statement + 
that*",
+        "     @ must + be + wrapped + properly",
+        "      this = is + a + long + and + nasty + fortran + statement +   
that*",
+        "     @ must + be + wrapped + properly",
+        "      this = is + a + long + and + nasty + fortran + statement +    
that",
+        "     @ *must + be + wrapped + properly",
+        "      this = is + a + long + and + nasty + fortran + statement +",
+        "     @ that*must + be + wrapped + properly",
+        "      this = is + a + long + and + nasty + fortran + statement + 
that**",
+        "     @ must + be + wrapped + properly",
+        "      this = is + a + long + and + nasty + fortran + statement +  
that**",
+        "     @ must + be + wrapped + properly",
+        "      this = is + a + long + and + nasty + fortran + statement +   
that",
+        "     @ **must + be + wrapped + properly",
+        "      this = is + a + long + and + nasty + fortran + statement +    
that",
+        "     @ **must + be + wrapped + properly",
+        "      this = is + a + long + and + nasty + fortran + statement +",
+        "     @ that**must + be + wrapped + properly",
+        "      this = is + a + long + and + nasty + fortran + 
statement(that)/",
+        "     @ must + be + wrapped + properly",
+        "      this = is + a + long + and + nasty + fortran +     
statement(that)",
+        "     @ /must + be + wrapped + properly",
+    ]
+    for line in wrapped_lines:
+        assert len(line) <= 72
+    for w, e in zip(wrapped_lines, expected_lines):
+        assert w == e
+    assert len(wrapped_lines) == len(expected_lines)
+
-- 
1.6.3.3

-- 
You received this message because you are subscribed to the Google Groups 
"sympy-patches" group.
To post to this group, send email to sympy-patc...@googlegroups.com.
To unsubscribe from this group, send email to 
sympy-patches+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sympy-patches?hl=en.

Reply via email to