
    wg?             
          d Z ddlZddlZddlmZ ddlmZ ddlm	Z	m
Z
mZmZmZmZ ddlmZ ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZmZmZ ddlm Z m!Z!m"Z"m#Z#m$Z$ ddl%m&Z& g dZ' G d d      Z( G d d      Z) e)dddddd       e)dddddd       e)dddddd      dZ*dZ+dGd Z, G d! d"      Z- G d# d$e-      Z. G d% d&e.      Z/ G d' d(      Z0 G d) d*e.e0      Z1 G d+ d,e.e0      Z2 G d- d.e-e0      Z3 G d/ d0      Z4 G d1 d2e5      Z6 G d3 d4e5      Z7d5Z8 G d6 d7e4      Z9 G d8 d9e9      Z: G d: d;e9      Z; G d< d=e4      Z< G d> d?e4      Z= G d@ dAe4      Z> G dB dCe4      Z?dHdDZ@	 	 	 dIdEZA	 	 dJdFZBy)Ka%  
module for generating C, C++, Fortran77, Fortran90, Julia, Rust
and Octave/Matlab routines that evaluate SymPy expressions.
This module is work in progress.
Only the milestones with a '+' character in the list below have been completed.

--- How is sympy.utilities.codegen different from sympy.printing.ccode? ---

We considered the idea to extend the printing routines for SymPy functions in
such a way that it prints complete compilable code, but this leads to a few
unsurmountable issues that can only be tackled with dedicated code generator:

- For C, one needs both a code and a header file, while the printing routines
  generate just one string. This code generator can be extended to support
  .pyf files for f2py.

- SymPy functions are not concerned with programming-technical issues, such
  as input, output and input-output arguments. Other examples are contiguous
  or non-contiguous arrays, including headers of other libraries such as gsl
  or others.

- It is highly interesting to evaluate several SymPy functions in one C
  routine, eventually sharing common intermediate results with the help
  of the cse routine. This is more than just printing.

- From the programming perspective, expressions with constants should be
  evaluated in the code generator as much as possible. This is different
  for printing.

--- Basic assumptions ---

* A generic Routine data structure describes the routine that must be
  translated into C/Fortran/... code. This data structure covers all
  features present in one or more of the supported languages.

* Descendants from the CodeGen class transform multiple Routine instances
  into compilable code. Each derived class translates into a specific
  language.

* In many cases, one wants a simple workflow. The friendly functions in the
  last part are a simple api on top of the Routine/CodeGen stuff. They are
  easier to use, but are less powerful.

--- Milestones ---

+ First working version with scalar input arguments, generating C code,
  tests
+ Friendly functions that are easier to use than the rigorous
  Routine/CodeGen workflow.
+ Integer and Real numbers as input and output
+ Output arguments
+ InputOutput arguments
+ Sort input/output arguments properly
+ Contiguous array arguments (numpy matrices)
+ Also generate .pyf code for f2py (in autowrap module)
+ Isolate constants and evaluate them beforehand in double precision
+ Fortran 90
+ Octave/Matlab

- Common Subexpression Elimination
- User defined comments in the generated code
- Optional extra include lines for libraries/objects that can eval special
  functions
- Test other C compilers and libraries: gcc, tcc, libtcc, gcc+gsl, ...
- Contiguous array arguments (SymPy matrices)
- Non-contiguous array arguments (SymPy matrices)
- ccode must raise an error when it encounters something that cannot be
  translated into c. ccode(integrate(sin(x)/x, x)) does not make sense.
- Complex numbers as input and output
- A default complex datatype
- Include extra information in the header: date, user, hostname, sha1
  hash, ...
- Fortran 77
- C++
- Python
- Julia
- Rust
- ...

    N)StringIO)__version__)SymbolSTupleEqualityFunctionBasic)c_code_printers)AssignmentError)FCodePrinter)JuliaCodePrinter)OctaveCodePrinter)RustCodePrinter)IdxIndexedIndexedBase)MatrixSymbolImmutableMatrix
MatrixBase
MatrixExprMatrixSlice)is_sequence)RoutineDataTypedefault_datatypesget_default_datatypeArgumentInputArgumentOutputArgumentResultCodeGenCCodeGenFCodeGenJuliaCodeGenOctaveCodeGenRustCodeGencodegenmake_routinec                   @    e Zd ZdZd Zd ZeZed        Zed        Z	y)r   a  Generic description of evaluation routine for set of expressions.

    A CodeGen class can translate instances of this class into code in a
    particular language.  The routine specification covers all the features
    present in these languages.  The CodeGen part must raise an exception
    when certain features are not present in the target language.  For
    example, multiple return values are possible in Python, but not in C or
    Fortran.  Another example: Fortran and Python support complex numbers,
    while C does not.

    c                    t               }t               }|D ]  }t        |t              rF|j                  |j                  j
                  |j                  j                  t              z
         Zt        |t              r|j                  |j                         t        |t              ra|j                  |j                         |j                  |j                  j
                  |j                  j                  t              z
         t        d|z         |D ]e  }	t        |	t              st        d|	z        |j                  |	j                  j
                  |	j                  j                  t              z
         g t               }
|D ]  }	t        |	t              ra|j                  |	j                  j
                  |	j                  j                  t              z
         |
j                  |	j                         t|
j                  |	        |D ch c]   }t        |t              r|j                  n|" }}|j!                  |j#                  |
      j#                  |            }|t               k7  r4t        ddj%                  |D cg c]  }t'        |       c}      z         || _
        || _        || _        || _        || _        yc c}w c c}w )a  Initialize a Routine instance.

        Parameters
        ==========

        name : string
            Name of the routine.

        arguments : list of Arguments
            These are things that appear in arguments of a routine, often
            appearing on the right-hand side of a function call.  These are
            commonly InputArguments but in some languages, they can also be
            OutputArguments or InOutArguments (e.g., pass-by-reference in C
            code).

        results : list of Results
            These are the return values of the routine, often appearing on
            the left-hand side of a function call.  The difference between
            Results and OutputArguments and when you should use each is
            language-specific.

        local_vars : list of Results
            These are variables that will be defined at the beginning of the
            function.

        global_vars : list of Symbols
            Variables which will not be passed into the function.

        zUnknown Routine argument: %szUnknown Routine result: %sz+Symbols needed for output are not in input , N)set
isinstancer    updateexprfree_symbolsatomsr   r   addnameInOutArgument
ValueErrorr!   r   label
differenceunionjoinstr	argumentsresults
local_varsglobal_vars)selfr4   r<   r=   r>   r?   input_symbolssymbolsargrlocal_symbolss
notcoveredxs                 \/home/mcse/projects/flask/flask-venv/lib/python3.12/site-packages/sympy/utilities/codegen.py__init__zRoutine.__init__   sK   @ % 		GC#~.sxx44sxx~~g7NNOC/!!#((+C/!!#((+sxx44sxx~~g7NNO !?#!EFF		G  	HAa( !=!ABBNN166..g1FFG	H
  	%A!V$qvv22QVV\\'5JJK!!!&&)!!!$	% BIIAjC0177a7II
 ''.44[AC
J!YY
'C1A'CDE F F 	"$& J (Ds   %KKc                 h    | j                   j                   dj                  di | j                  z   S )Nz?({name!r}, {arguments}, {results}, {local_vars}, {global_vars}) )	__class____name__format__dict__r@   s    rI   __str__zRoutine.__str__   sD    ~~&&)q)j)q)q  *Ctx  uB  uB  *C  C  	C    c                     t        | j                        }|j                  d | j                  D               |j                  d | j                  D               |S )zReturns a set of all variables possibly used in the routine.

        For routines with unnamed return values, the dummies that may or
        may not be used will be included in the set.

        c              3   4   K   | ]  }|j                     y wNr4   ).0rC   s     rI   	<genexpr>z$Routine.variables.<locals>.<genexpr>   s     4c4   c              3   4   K   | ]  }|j                     y wrV   )
result_var)rX   ress     rI   rY   z$Routine.variables.<locals>.<genexpr>   s     8C8rZ   )r-   r>   r/   r<   r=   )r@   vs     rI   	variableszRoutine.variables   sC      	4T^^44	84<<88rS   c                     | j                   D cg c]  }t        |t        t        f      s| }}|j	                  | j
                         |S c c}w )zReturns a list of OutputArgument, InOutArgument and Result.

        If return values are present, they are at the end of the list.
        )r<   r.   r    r5   extendr=   )r@   rC   argss      rI   result_variableszRoutine.result_variables   sL      $~~ 3.-022 3 3DLL!3s
   AAN)
rN   
__module____qualname____doc__rJ   rR   __repr__propertyr_   rc   rL   rS   rI   r   r   u   sA    
I'VC H
 
  rS   r   c                       e Zd ZdZd Zy)r   z<Holds strings for a certain datatype in different languages.c                 X    || _         || _        || _        || _        || _        || _        y rV   )cnamefnamepynamejlnameoctnamersname)r@   rk   rl   rm   rn   ro   rp   s          rI   rJ   zDataType.__init__   s,    

rS   N)rN   rd   re   rf   rJ   rL   rS   rI   r   r      s
    FrS   r   intz	INTEGER*4 i32doublezREAL*8floatf64z
COMPLEX*16complex)rq   ru   rw   Fc                 *   |t         }|rd}nd}| j                  r	t        d   S | j                  r	t        d   S t	        | t
              rBd}| D ]2  }|dk(  r|j                  sd}|dk(  s|j                  r)t        |   c S  t        |   S t        |   S )z8Derives an appropriate datatype based on the expression.rw   ru   rq   )COMPLEX_ALLOWED
is_integerr   is_realr.   r   )r0   complex_allowedfinal_dtypedtelements        rI   r   r     s    ) ''	 ))	D*	% 	6GU{7#5#5W}W__(55		6
 !$$ --rS   c                   8    e Zd ZdZddZd ZeZed        Zd Z	y)VariablezRepresents a typed variable.Nc                    t        |t        t        f      st        d      |t	        |      }nt        |t
              st        d      |r!t        |t        t        f      st        d      || _        |j                  |j                  |j                  |j                  |j                  |j                  d| _        || _        || _        y)aT  Return a new variable.

        Parameters
        ==========

        name : Symbol or MatrixSymbol

        datatype : optional
            When not given, the data type will be guessed based on the
            assumptions on the symbol argument.

        dimensions : sequence containing tuples, optional
            If present, the argument is interpreted as an array, where this
            sequence of tuples specifies (lower, upper) bounds for each
            index of the array.

        precision : int, optional
            Controls the precision of floating point constants.

        z*The first argument must be a SymPy symbol.NzMThe (optional) `datatype' argument must be an instance of the DataType class.z4The dimensions argument must be a sequence of tuples)CFORTRANJULIAOCTAVEPYTHONRUST)r.   r   r   	TypeErrorr   r   tuplelist_namerk   rl   rn   ro   rm   rp   	_datatype
dimensions	precision)r@   r4   datatyper   r   s        rI   rJ   zVariable.__init__  s    * $ 67HII+D1HHh/ > ? ?jeT]CFH H 
~~__&&ooOO
 %"rS   c                 N    | j                   j                  d| j                  dS )N())rM   rN   r4   rQ   s    rI   rR   zVariable.__str__J  s    >>22DII>>rS   c                     | j                   S rV   )r   rQ   s    rI   r4   zVariable.nameO  s    zzrS   c                     	 | j                   |j                            S # t        $ r( t        ddj	                  | j                         z        w xY w)aQ  Returns the datatype string for the requested language.

        Examples
        ========

        >>> from sympy import Symbol
        >>> from sympy.utilities.codegen import Variable
        >>> x = Variable(Symbol('x'))
        >>> x.get_datatype('c')
        'double'
        >>> x.get_datatype('fortran')
        'REAL*8'

        zHas datatypes for languages: %sr,   )r   upperKeyErrorCodeGenErrorr:   )r@   languages     rI   get_datatypezVariable.get_datatypeS  sQ    	/>>(.."233 	/@IIdnn- . / /	/s	    1ANNN)
rN   rd   re   rf   rJ   rR   rg   rh   r4   r   rL   rS   rI   r   r     s.    &*#X? H /rS   r   c                       e Zd ZdZy)r   z{An abstract Argument data structure: a name and a data type.

    This structure is refined in the descendants below.

    N)rN   rd   re   rf   rL   rS   rI   r   r   i  s    
 	rS   r   c                       e Zd Zy)r   NrN   rd   re   rL   rS   rI   r   r   r      rS   r   c                        e Zd ZdZd Zd ZeZy)
ResultBasezBase class for all "outgoing" information from a routine.

    Objects of this class stores a SymPy expression, and a SymPy object
    representing a result variable that will be used in the generated code
    only if necessary.

    c                      || _         || _        y rV   )r0   r\   )r@   r0   r\   s      rI   rJ   zResultBase.__init__~  s    	$rS   c                 h    | j                   j                  d| j                  d| j                  dS Nr   r,   r   )rM   rN   r0   r\   rQ   s    rI   rR   zResultBase.__str__  s&    #~~66		OO 	rS   NrN   rd   re   rf   rJ   rR   rg   rL   rS   rI   r   r   v  s    % HrS   r   c                   "    e Zd ZdZddZd ZeZy)r    z5OutputArgument are always initialized in the routine.Nc                 d    t         j                  | ||||       t        j                  | ||       y)ar  Return a new variable.

        Parameters
        ==========

        name : Symbol, MatrixSymbol
            The name of this variable.  When used for code generation, this
            might appear, for example, in the prototype of function in the
            argument list.

        result_var : Symbol, Indexed
            Something that can be used to assign a value to this variable.
            Typically the same as `name` but for Indexed this should be e.g.,
            "y[i]" whereas `name` should be the Symbol "y".

        expr : object
            The expression that should be output, typically a SymPy
            expression.

        datatype : optional
            When not given, the data type will be guessed based on the
            assumptions on the symbol argument.

        dimensions : sequence containing tuples, optional
            If present, the argument is interpreted as an array, where this
            sequence of tuples specifies (lower, upper) bounds for each
            index of the array.

        precision : int, optional
            Controls the precision of floating point constants.

        N)r   rJ   r   r@   r4   r\   r0   r   r   r   s          rI   rJ   zOutputArgument.__init__  s-    D 	$h
IFD$
3rS   c                     | j                   j                  d| j                  d| j                  d| j                  dS r   )rM   rN   r4   r\   r0   rQ   s    rI   rR   zOutputArgument.__str__  s*    #'>>#:#:DIItX\XaXabbrS   r   r   rL   rS   rI   r    r      s    ?#4Jc HrS   r    c                   X    e Zd ZdZddZej                  j                  e_        d ZeZy)r5   z3InOutArgument are never initialized in the routine.Nc                 ~    |st        |      }t        j                  | ||||       t        j                  | ||       y rV   )r   r   rJ   r   r   s          rI   rJ   zInOutArgument.__init__  s7    +D1H$h
IFD$
3rS   c                     | j                   j                  d| j                  d| j                  d| j                  dS r   )rM   rN   r4   r0   r\   rQ   s    rI   rR   zInOutArgument.__str__  ,    #'>>#:#:DIItyyOO 	rS   r   )rN   rd   re   rf   rJ   r    rR   rg   rL   rS   rI   r5   r5     s,    =4
 &..66H HrS   r5   c                   &    e Zd ZdZ	 	 ddZd ZeZy)r!   a9  An expression for a return value.

    The name result is used to avoid conflicts with the reserved word
    "return" in the Python language.  It is also shorter than ReturnValue.

    These may or may not need a name in the destination (e.g., "return(x*y)"
    might return a value without ever naming it).

    Nc                    t        |t        t        f      st        d      |dt	        t        |            z  }|t        |      }t        |t              r8t        |t        t        f      rt        |g|j                   }nt        |      }||}t        j                  | ||||       t        j                  | ||       y)a  Initialize a return value.

        Parameters
        ==========

        expr : SymPy expression

        name : Symbol, MatrixSymbol, optional
            The name of this return variable.  When used for code generation,
            this might appear, for example, in the prototype of function in a
            list of return values.  A dummy name is generated if omitted.

        result_var : Symbol, Indexed, optional
            Something that can be used to assign a value to this variable.
            Typically the same as `name` but for Indexed this should be e.g.,
            "y[i]" whereas `name` should be the Symbol "y".  Defaults to
            `name` if omitted.

        datatype : optional
            When not given, the data type will be guessed based on the
            assumptions on the expr argument.

        dimensions : sequence containing tuples, optional
            If present, this variable is interpreted as an array,
            where this sequence of tuples specifies (lower, upper)
            bounds for each index of the array.

        precision : int, optional
            Controls the precision of floating point constants.

        z.The first argument must be a SymPy expression.Nz	result_%d)r   r   r   )r.   r
   r   r   abshashr   r;   r   r   shaper   r   rJ   r   )r@   r0   r4   r\   r   r   r   s          rI   rJ   zResult.__init__  s    D $
 34LMM<T$Z0D+D1HdC $Z 89#D64::6d|J$x%/9 	 	FD$
3rS   c                     | j                   j                  d| j                  d| j                  d| j                  dS r   )rM   rN   r0   r4   r\   rQ   s    rI   rR   zResult.__str__  r   rS   )NNNNNr   rL   rS   rI   r!   r!     s#     CG,074r HrS   r!   c                   H    e Zd ZdZdZd Zd
dZd ZddZddZ	ddZ
dd	Zy)r"   z'Abstract class for the code generators.Nc                 8    | j                   j                  |      S rV   )printerindent_coder@   	codeliness     rI   _indent_codezCodeGen._indent_code  s    ||''	22rS   c                 f   |xs i }|D ci c]  }|| j                   j                  |    }}|j                         D ]  \  }}|| j                   j                  |<      t        | j                   |      |i |}|j                         D ]  \  }}|| j                   j                  |<     |S c c}w rV   )r   	_settingsitemsgetattr)	r@   methodsettingsrb   kwargskorir^   results	            rI   _printer_method_with_settingsz%CodeGen._printer_method_with_settings   s    >r5=>q$,,((++>>NN$ 	*DAq()DLL""1%	*.v.??IIK 	*DAq()DLL""1%	* ?s   !B.c                    | j                   j                  d   r+| j                   j                  |      }|j                         S | j                   j                  |      \  }}}|s|rt        dt	        |      z        |j                         S )z&Returns the symbol as fcode prints it.humanzFailed to print %s)r   r   doprintr6   r;   strip)r@   rF   expr_str	constantsnot_supporteds        rI   _get_symbolzCodeGen._get_symbol*  s{    <<!!'*||++A.H
 ~~ 261E1Ea1H.I}hM !5A!>??~~rS   c                      || _         || _        y)zInitialize a code generator.

        Derived classes will offer more options that affect the generated
        code.

        Nprojectcse)r@   r   r   s      rI   rJ   zCodeGen.__init__4  s     rS   c           
         | j                   rRddlm } t        |      rt        |t        t
        f      s|st        d      |D ](  }|j                  rt        dj                  |             |D cg c]  }|j                   }} ||      \  }}	t        ||	      D cg c]  \  }}t        |j                  |       }}}nLt        |t              r/ ||j                        \  }}	t        |j                  |	d         }n ||      \  }}	|	}|D 
cg c]  \  }
}t        ||
       }}
}|D 
ch c]  \  }
}|
	 }}
}t        |D cg c]  \  }}|	 c}} }n
t               }t        |      r,t        |t        t
        f      s|st        d      t        | }nt        |      }| j                   rC|j!                  t"              D ch c]  }|j$                   c}t'               k7  r9t        d      |j!                  t"              D ch c]  }|j$                   }}|}|
t'               n
t'        |      }|j(                  |j(                  z  z
  |z
  }t'               }|j+                  |       |D ]m  }t        |t"              r9|j-                  |       |j+                  |j.                  d   j(                         t        |t0              s]|j-                  |       o |}g }g }|D ]
  }t        |t              rE|j                  }|j                  }t        |t0              rMt3        |j4                  D cg c]  }t6        j8                  |dz
  f c}      }|j:                  j$                  }nit        |t<              rg }|}nTt        |t>              r9t3        |j4                  D cg c]  }t6        j8                  |dz
  f c}      }|}nt        d      |jA                  |      r|jC                  tE        ||||             n|jC                  tG        ||||             |vsG|j-                  |       Zt        |tH        tJ        f      rt?        d	tM        tO        |            z  g|j4                   }t3        |j4                  D cg c]  }t6        j8                  |dz
  f c}      }|jC                  tG        ||||             |jC                  t        |              g }d
 }i }|j!                  t0              |j!                  t0              z  D ]  }|||j:                  j$                  <    |j!                  t>              |j!                  t>              z  D ]  }|||<   	 tQ        |tR              D ]3  }||v r||   }d ||      i}ni }|jC                  tU        |fi |       5 |jW                  d        |jY                  |       |g }|D ]?  } t        | tZ              r|jC                  | j$                         /|jC                  |        A |}|D !cg c]  }!|!j\                  |vs|! }"}!|"rOd}#|#j                  dj_                  |"D $cg c]  }$tS        |$j\                         c}$            }#ta        |#|"      |D !ci c]  }!|!j\                  |! }%}!g }&|D ]  }	 |&jC                  |%|           |&}te        ||||      S c c}w c c}}w c c}}
w c c}}
w c c}}w c c}w c c}w c c}w c c}w c c}w c c}!w c c}$w c c}!w # tb        $ rA t        |tZ        t>        f      rd ||      i}ni }|&jC                  tU        |fi |       Y w xY w)aq  Creates an Routine object that is appropriate for this language.

        This implementation is appropriate for at least C/Fortran.  Subclasses
        can override this if necessary.

        Here, we assume at most one return value (the l-value) which must be
        scalar.  Additional outputs are OutputArguments (e.g., pointers on
        right-hand-side or pass-by-reference).  Matrices are always returned
        via OutputArguments.  If ``argument_sequence`` is None, arguments will
        be ordered alphabetically, but with all InputArguments first, and then
        OutputArgument and InOutArguments.

        r   )r   No expression givenz7Lists of expressions must all be Equalities. {} is not.z9CSE and Indexed expressions do not play well together yet   BOnly Indexed, Symbol, or MatrixSymbol can define output arguments.r   zout_%sc                 f    | j                   D cg c]  }t        j                  |dz
  f c}S c c}w Nr   )r   r   Zero)rF   dims     rI   r   z#CodeGen.routine.<locals>.dimensions  s'    129#QVVS1W%999s   .keyr   c                 ,    t        | j                        S rV   r;   r4   rH   s    rI   <lambda>z!CodeGen.routine.<locals>.<lambda>      s166{ rS   "Argument list didn't specify: {0} r,   )3r   sympy.simplify.cse_mainr   r.   r   r   r6   is_Equalityr   rO   rhszipr   lhsr!   r   r2   r   r7   r-   r1   r/   removerb   r   r   r   r   r   baser   r   hasappendr5   r    r   r   r   r   sortedr;   r   sortra   r   r4   r:   CodeGenArgumentListErrorr   r   )'r@   r4   r0   argument_sequencer?   r   er   common
simplifiedabr>   _rE   local_expressionsexpressionsirB   new_symbolssymbol
return_valoutput_argsout_argr   dimsarg_listr   array_symbolsarraymetadatanew_sequencerC   rH   missingmsgmname_arg_dictnew_argss'                                          rI   routinezCodeGen.routine>  s    8834 D:z:R)S$%:;; pA==*+d+k+klm+noop
 '++quu++%(X"
 <?tZ;PQC,QQdH-),TXX&FJ#DHHjm<D),T&FJ%D178#!A&1+8J8*0131QQ1M1 %V'<ca'< = %tZz:6N%O !677,K+K88!,!2!23!78A8CEA"#^__ ,7+<+<S+ABa!''BJB&M  +2ceK8H ++.?.L.LLP]]`kke7# 	+F&#&""6*""6;;q>#>#>?&'*""6*	+  
 #	0D$)((xxgw/ !NAFFC!G#4!NOD$\\//F0D$F6 !NAFFC!G#4!NOD$F& (F G G 88F#&&%fgtMO  &&&vwNP +NN6*D?K"@A&x#d4j/'AODJJO7==ICqvvsQw/IJ"""7GTdKM !!&,/G#	0J 
	:  &&w/2C2I2I'2RR 	4E.3M%****+	4 &&|47H7N7N|7\\ 	)E#(M% 	) W#. 	?F&%f-(*U*;<OOM&=H=>	? 	23$(L( -c;/ ''		2 '',	-
 !-"*NQaff<M.MqNGN:jj+IACK+I!JK.sG<< 1991QVVQY9M9H+ GGOOM&$9:G  HtXz:{KKe , R 91'< 9 C6 "O "O( JT O ,J :
   G!&;*EF$0*V2D#E#%OOM&$EH$EFGsg   3[4" [9[?5\\
\\\
6\ 
"\%
 \*\*8\//\4\99A^^c           
      d   |rE| j                   D ]5  }|d|j                  }t        |d      5 } || |||||       ddd       7 yg }	| j                   D ]K  }|d|j                  }t               }
 || ||
|||       |	j	                  ||
j                         f       M |	S # 1 sw Y   xY w)a  Writes all the source code files for the given routines.

        The generated source is returned as a list of (filename, contents)
        tuples, or is written to files (see below).  Each filename consists
        of the given prefix, appended with an appropriate extension.

        Parameters
        ==========

        routines : list
            A list of Routine instances to be written

        prefix : string
            The prefix for the output files

        to_files : bool, optional
            When True, the output is written to files.  Otherwise, a list
            of (filename, contents) tuples is returned.  [default: False]

        header : bool, optional
            When True, a header comment is included on top of each source
            file. [default: True]

        empty : bool, optional
            When True, empty lines are included to structure the source
            files. [default: True]

        .wN)dump_fns	extensionopenr   r   getvalue)r@   routinesprefixto_filesheaderemptydump_fnfilenamefr   contentss              rI   writezCodeGen.write  s    : == F&,g.?.?@(C( FAD(AvvuEF FF
 F== ?&,g.?.?@#:h&&%Hx):):)<=>	?
 MF Fs   B&&B/	c                    | j                  |      }|D ]  }|r|j                  d       |j                  | j                  |             |j                  | j	                  |             |j                  | j                  |             |j                  | j                  |             |r|j                  d       |j                  | j                  |             |r|j                  d       |j                  | j                  |              | j                  dj                  |            }|r#dj                  | j                         |gz         }|r|j                  |       yy)a(  Write the code by calling language specific methods.

        The generated file contains all the definitions of the routines in
        low-level code and refers to the header file if appropriate.

        Parameters
        ==========

        routines : list
            A list of Routine instances.

        f : file-like
            Where to write the file.

        prefix : string
            The filename prefix, used to refer to the proper header file.
            Only the basename of the prefix is used.

        header : bool, optional
            When True, a header comment is included on top of each source
            file.  [default : True]

        empty : bool, optional
            When True, empty lines are included to structure the source
            files.  [default : True]

        
rr   N)_preprocessor_statementsr   ra   _get_routine_opening_declare_arguments_declare_globals_declare_locals_call_printer_get_routine_endingr   r:   _get_headerr  )r@   r  r  r  r  r  
code_linesr	  s           rI   	dump_codezCodeGen.dump_code  s>   : 226:
 	AG!!$'d77@Ad55g>?d33G<=d227;<!!$'d009:!!$'d66w?@	A &&rwwz':;
!1!1!3zl!BCJGGJ rS   rV   )r   F)NN)FTTTT)rN   rd   re   rf   r   r   r   r   rJ   r	  r  r&  rL   rS   rI   r"   r"     s1    1G3 lL\)V3 rS   r"   c                       e Zd Zy)r   Nr   rL   rS   rI   r   r   M  r   rS   r   c                       e Zd Zed        Zy)r   c                      | j                   d   S r   )rb   rQ   s    rI   missing_argsz%CodeGenArgumentListError.missing_argsR  s    yy|rS   N)rN   rd   re   rh   r+  rL   rS   rI   r   r   Q  s     rS   r   z{Code generated with SymPy %(version)s

See http://www.sympy.org/ for more information.

This file is part of '%(project)s'
c                        e Zd ZdZdZdZdZ	 	 d fd	Zd Zd Z	d Z
d	 Zd
 Zd Zd Zd Zd ZddZee_        ej(                  j                  e_        ddZee_        eegZ xZS )r#   zGenerator for C code.

    The .write() method inherited from CodeGen will output a code file and
    an interface file, <prefix>.c and <prefix>.h respectively.

    chc99c                     t         |   ||       |xs% t        | j                  j	                                   | _        || _        |	dg| _        y y )Nr   z#include <math.h>)superrJ   r   standardlowerr   preprocessor_statements)r@   r   r   r4  r   rM   s        rI   rJ   zCCodeGen.__init__k  sT    c2J/$--2E2E2G"H"J'>$"*,?+@D( +rS   c                     g }|j                  d       t        t        | j                  dz  }|j	                         D ]%  }|j                  d|j                  d      z         ' |j                  d       |S )/Writes a common header for the generated files.zP/******************************************************************************
versionr   z *%s*
L   zQ ******************************************************************************/
r   header_commentsympy_versionr   
splitlinescenterr@   r%  tmplines       rI   r$  zCCodeGen._get_headert  st    
-.=+/<< 9 9NN$ 	;Di$++b/9:	;./rS   c                 j   t        |j                        dkD  rt        d      t        |j                        dk(  r|j                  d   j                  d      }nd}g }|j                  D ]  }| j
                  j                  |j                        }|j                  st        |t              r&|j                  |j                  d      d|z  f       j|j                  |j                  d      |f        dj                  |D cg c]  }d|z  	 c}      }|d	|j                  d
|dS c c}w )Returns a string for the function prototype of the routine.

        If the routine has multiple result objects, an CodeGenError is
        raised.

        See: https://en.wikipedia.org/wiki/Function_prototype

        r   z,C only supports a single or no return value.r   r   void*%sr,   z%s %s r   r   )lenr=   r   r   r<   r   r   r4   r   r.   r   r   r:   )r@   r	  ctype	type_argsrC   r4   tr<   s           rI   get_prototypezCCodeGen.get_prototype  s
    w!#MNN!Q&OOA&33C8EE	$$ 	@C<<''1D~~C!<  #"2"23"7!FG  #"2"23"7!>?	@ IIY?!?@	#W\\9== @s   D0c                     g }|j                  dj                  t        j                  j	                  |                   |j                  | j                         |D cg c]  }dj                  |       }}|S c c}w )Nz#include "{}.h"z{}
)r   rO   ospathbasenamera   r4  )r@   r  r%  ls       rI   r  z!CCodeGen._preprocessor_statements  sk    
+222773C3CF3KLM$6670:;1fmmA&;
; <s   A;c                 0    | j                  |      }d|z  gS Nz%s {
rK  r@   r	  	prototypes      rI   r  zCCodeGen._get_routine_opening       &&w/	9$%%rS   c                     g S rV   rL   r@   r	  s     rI   r  zCCodeGen._declare_arguments      	rS   c                     g S rV   rL   rX  s     rI   r   zCCodeGen._declare_globals  rY  rS   c           
      x   g }|j                   D ];  }t        |t              s|j                  r!|j	                  |j
                         = g }|j                  D ][  }t        |t              s|j
                  |j                  k7  rt        dj                  |            |j
                  }|j                  d      }t        |j                  t        t        f      rM|j                  j                  }|j	                  dj                  |t!        |      |d   |d   z               d}	ndj                  |      }	| j#                  dd	|d	d
|j                  |      \  }
}}t%        |
t               D ]  \  }}|j	                  d|d|d        |j	                  dj                  |	|             ^ |S )Nz)Result variable and name should match: {}r-  z{} {}[{}];
r   r   rr   z	const {} r   Fr   dereferencestrict	assign_tor   double const  = ;
z{}{}
)r<   r.   r   r   r   r4   r>   r!   r\   r"   rO   r   r0   r   r   r   r;   r   r   )r@   r	  r]  rC   r%  r   r`  rJ  r   r  r   not_cc_exprr4   values                  rI   r!  zCCodeGen._declare_locals  s   
 $$ 	-C#z*3>>""388,	- 
(( 	?F ff-{{f///IPPQWXYYI##C(A&++
J'?@{{((!!."7"73y>4PQ7SWXYSZ?"[\$++A.'+'I'IU;RWXy (J (2$Iuf  &iS9 Me!!tU"KLM hooff=>3	?6 rS   c           	         g }g }|j                   D ];  }t        |t              s|j                  r!|j	                  |j
                         = d }|j                  D ]  }t        |t              rM|j
                  dz   }|j                  d      }|j	                  dj                  |t        |                   |}n|j                  }	 | j                  dd|dd|j                  |      \  }	}
}t        |	t        
      D ]  \  }}|j	                  d|d|d	        |j	                  d|z          |r|j	                  d|z         |S # t        $ re |j                  }|j	                  |j                  d      dt        |      d	       | j                  dd|dd|j                  |      \  }	}
}Y w xY w)N_resultr-  z{} {};
r   Fr\  r_  rF  rc  r   ra  rb  %s
z   return %s;
)r<   r.   r   r   r   r4   rc   r!   r   rO   r;   r\   r   r0   r   r   )r@   r	  r%  r]  rC   r   r   r`  rJ  r   rd  re  r4   rf  s                 rI   r"  zCCodeGen._call_printer  s   

 $$ 	-C#z*3>>""388,	- 
.. 	/F&&)#LL94	'',!!*"3"3As9~"FG&
"--	
6+/+M+M{V[\KK9 ,N ,6(	5&  &iS9 Me!!tU"KLMfvo./	/2 /*<= # 6"--	!!"("5"5c":C	NKM+/+M+M{V[\KK9 ,N ,6(	5&	6s   
'EA+F>=F>c                     dgS Nz}
rL   rX  s     rI   r#  zCCodeGen._get_routine_ending  	    wrS   c                 .    | j                  |||||       y rV   r&  r@   r  r  r  r  r  s         rI   dump_czCCodeGen.dump_c       xFFE:rS   c                    |r*t        dj                  | j                               |       | j                  j	                  dd      j                         d|j	                  dd      j                         d}|rt        |       t        d|z  |       t        d	|z  |       |rt        |       |D ]#  }| j                  |      }t        d
|z  |       % |rt        |       t        d|       |rt        |       yy)a  Writes the C header file.

        This file contains all the function declarations.

        Parameters
        ==========

        routines : list
            A list of Routine instances.

        f : file-like
            Where to write the file.

        prefix : string
            The filename prefix, used to construct the include guards.
            Only the basename of the prefix is used.

        header : bool, optional
            When True, a header comment is included on top of each source
            file.  [default : True]

        empty : bool, optional
            When True, empty lines are included to structure the source
            files.  [default : True]

        rr   filerF  r   __/__Hz
#ifndef %sz
#define %sz%s;z#endifN)printr:   r$  r   replacer   rK  )	r@   r  r  r  r  r  
guard_namer	  rU  s	            rI   dump_hzCCodeGen.dump_h  s    6 "''$**,-A6$(LL$8$8%eg%%~~c37==?A
 qMlZ'a0lZ'a0qM 	-G**73I%)#!,	- qMhQqM rS   )r   NNFr'  )rN   rd   re   rf   code_extensioninterface_extensionr2  rJ   r$  rK  r  r  r  r   r!  r"  r#  rp  r  r"   r&  r{  r  __classcell__rM   s   @rI   r#   r#   _  s     NH2638A	>4&&P'R;%F&&..FN/` +F HrS   r#   c                       e Zd ZdZy)
C89CodeGenC89NrN   rd   re   r2  rL   rS   rI   r  r  ;      HrS   r  c                       e Zd ZdZy)
C99CodeGenC99Nr  rL   rS   rI   r  r  >  r  rS   r  c                        e Zd ZdZdZdZd fd	Zd Zd Zd Z	d Z
d	 Zd
 Zd Zd Zd Zd ZddZee_        ej(                  j                  e_        ddZee_        eegZ xZS )r$   zGenerator for Fortran 95 code

    The .write() method inherited from CodeGen will output a code file and
    an interface file, <prefix>.f90 and <prefix>.h respectively.

    f90r.  c                 J    t         |   |       |xs
 t               | _        y rV   )r1  rJ   r   r   r@   r   r   rM   s      rI   rJ   zFCodeGen.__init__L  s    !0,.rS   c                     g }|j                  d       t        t        | j                  dz  }|j	                         D ]%  }|j                  d|j                  d      z         ' |j                  d       |S )r6  zP!******************************************************************************
r7  z!*%s*
r9  r:  r?  s       rI   r$  zFCodeGen._get_headerP  st    
-.=|| % %NN$ 	;Di$++b/9:	;-.rS   c                     g S rV   rL   r@   r  s     rI   r  z!FCodeGen._preprocessor_statements[      	rS   c                 b    g }t        |j                        dkD  rt        d      t        |j                        dk(  rA|j                  d   }|j                  |j	                  d             |j                  d       n|j                  d       dj                   fd|j                  D              }d	j                  |j                  |      }d
j                  t        j                  |dd            dz   }|j                  |       dj                  |      g}|j                  d       |S )z6Returns the opening statements of the fortran routine.r   z2Fortran only supports a single or no return value.r   fortranfunction
subroutiner,   c              3   Z   K   | ]"  }d j                  |j                        z   $ yw)%sN)r   r4   )rX   rC   r@   s     rI   rY   z0FCodeGen._get_routine_opening.<locals>.<genexpr>k  s-      6  0 0 :: 6s   (+z{}({})
z &
<   F)widthbreak_long_wordsr  rF  zimplicit none
)rG  r=   r   r   r   r:   r<   rO   r4   textwrapwrap)r@   r	  	code_listr   rb   call_sigs   `     rI   r  zFCodeGen._get_routine_opening^  s   	w!#DF F!Q&__Q'FV00;<Z(\*yy 6#*#4#46 6 $$W\\48 ;;x}}X35>C E FHLM 	"XXi()	*+rS   c                    g }g }g }|j                   D ]?  }t        |t              rd|j                  d      z  }nat        |t              rd|j                  d      z  }n<t        |t
              rd|j                  d      z  }nt        dt        |      z        | j                  }|j                  rwdj                  |j                  D cg c]!  } ||d   dz         d	 ||d   dz         # c}      }	|d
|	z  z  }|j                  |d ||j                        d       |j                  |d ||j                        d       B |j                  |       |j                  |       |S c c}w )Nz%s, intent(in)r  z%s, intent(inout)z%s, intent(out)zUnknown Argument type: %sr,   r   r   :z, dimension(%s) :: r  )r<   r.   r   r   r5   r    r   typer   r   r:   r   r4   ra   )
r@   r	  r  
array_listscalar_listrC   typeinfofprintr   dimstrs
             rI   r  zFCodeGen._declare_argumentsy  sh   	
$$ 	PC#}-+c.>.>y.IIC/.1A1A)1LLC0,s/?/?	/JJ"#>c#JKK%%F~~"~~$/ 3q6A:&s1vz(:%< $/ 0 -66!!(F388<L"MN""8VCHH=M#NO+	P0 	%$$/s   &E:
c                     g S rV   rL   rX  s     rI   r   zFCodeGen._declare_globals  s	     	rS   c                     g }t        |j                  t              D ]=  }t        |      }|j	                  |j
                  d| j                  |      d       ? |S )Nr   r  r  )r   r>   r;   r   r   rl   r   )r@   r	  r  varr  s        rI   r!  zFCodeGen._declare_locals  s\    	',,#6 	8C+C0H 0 0 57 8	8 rS   c                 >    t        |j                        dk(  rdgS dgS )z6Returns the closing statements of the fortran routine.r   zend function
zend subroutine
)rG  r=   rX  s     rI   r#  zFCodeGen._get_routine_ending  s%    w1$$%%&''rS   c                    dg}|j                  | j                  |             |j                  | j                  |             |j                  | j                  |             |j	                  d       dj                  |      S )a  Returns a string for the function interface.

        The routine should have a single result object, which can be None.
        If the routine has multiple result objects, a CodeGenError is
        raised.

        See: https://en.wikipedia.org/wiki/Function_prototype

        z
interface
zend interface
rr   )ra   r  r  r#  r   r:   rT  s      rI   get_interfacezFCodeGen.get_interface  su     $%	227;<009:11':;*+wwy!!rS   c           
         g }g }|j                   D ]'  }t        |t              r|j                  }n"t        |t        t
        f      r|j                  }| j                  dddddd|j                        \  }}}t        |t              D ]4  \  }	}
t        |	      }|j                  |j                  d|	d	|
d
       6 t        |t              D ]M  }	t        |	      }t        |	t              r|	j                  }n|	}|j                  |j                  d|d
       O |j                  d|z         * ||z   S )Nr   Ffree_   )r   source_formatr2  r^  r_  r   z, parameter :: rb  r  r  ri  )rc   r.   r!   r4   r    r5   r\   r   r0   r   r;   r   r   rl   r	   func)r@   r	  declarationsr%  r   r`  r   not_fortranf_exprobjr^   rJ  r4   s                rI   r"  zFCodeGen._call_printer  s=   
.. 	/F&&)#LL	F^]$CD"--	-1-O-OUVQS_dey .P .2*I{F !4 FQ(-##45GGS!DFF ks3 D(-c8,88DD##AGGT$BCD fvo.-	/. j((rS   c                 0    | j                  ddddd|      S )Nr   Fr  )r   r  r^  r   r   s     rI   r   zFCodeGen._indent_code  s&    11UVuUW`b 	brS   c                    |D ]  }|j                   D ch c]  }t        |      j                          }}|j                   D ch c]  }t        |       }	}t        |      t        |	      k  smt	        ddj                  |j                   D 
cg c]  }
t        |
       c}
      z         | j                  |||||       y c c}w c c}w c c}
w )Nz%Fortran ignores case. Got symbols: %sr,   )r_   r;   r3  rG  r   r:   r&  )r@   r  r  r  r  r  rD   rH   	lowercase	orig_caser  s              rI   dump_f95zFCodeGen.dump_f95  s     	HA12=AQ=I=)*5AQ5I59~I."#J#DCH#DE$G H H		H 	xFFE: >5 $Es    CC
Cc                     |r*t        dj                  | j                               |       |rt        |       |D ]$  }| j                  |      }|j	                  |       & |rt        |       yy)af  Writes the interface to a header file.

        This file contains all the function declarations.

        Parameters
        ==========

        routines : list
            A list of Routine instances.

        f : file-like
            Where to write the file.

        prefix : string
            The filename prefix.

        header : bool, optional
            When True, a header comment is included on top of each source
            file.  [default : True]

        empty : bool, optional
            When True, empty lines are included to structure the source
            files.  [default : True]

        rr   rs  N)rx  r:   r$  r  r  )r@   r  r  r  r  r  r	  rU  s           rI   r{  zFCodeGen.dump_h  si    4 "''$**,-A6qM 	G**73IGGI	 qM rS   r   Nr'  )rN   rd   re   rf   r|  r}  rJ   r$  r  r  r  r   r!  r#  r  r"  r   r  r  r"   r&  r{  r  r~  r  s   @rI   r$   r$   A  s     N1	6 D
("$)8b; (H((00H#H +F &!HrS   r$   c                        e Zd ZdZdZd fd	Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zd Zd ZddZee_        ej&                  j                  e_        egZ xZS )r%   zxGenerator for Julia code.

    The .write() method inherited from CodeGen will output a code file
    <prefix>.jl.

    jlc                 J    t         |   |       |xs
 t               | _        y rV   )r1  rJ   r   r   r  s      rI   rJ   zJuliaCodeGen.__init__"  s     !4"2"4rS   c           
      \   t        |      r,t        |t        t        f      s|st	        d      t        | }nt        |      }|j                  t              D ch c]  }|j                   }}|
t               n
t        |      }|j                  |z
  |z
  }t               }	|D ]]  }
t        |
t              r)|	j                  |
j                  d   j                         <t        |
t              rM|	j                  |
       _ g }g }t        |      D ]1  \  }}t        |t               r|j"                  }|j$                  }|}t        |t              rgt'        |j(                  D cg c]  }t*        j,                  |f c}      }|j.                  j                  }|j1                  t3        ||||             t        |t        t4        t6        f      st9        d      |j1                  t;        |||             |j=                  |      r|	j?                  |       |j1                  t;        |d|dz   z               4 |jA                  d 	       tC        |      }i }|j                  t              D ]  }|||j.                  j                  <    |j                  t6              D ]  }|||<   	 tE        |	tF        	      D ]  }|j1                  tI        |              |g }|D ]?  }t        |tJ              r|j1                  |j                         /|j1                  |       A |}|D cg c]  }|jL                  |vs| }}|rOd
}|jO                  djQ                  |D cg c]  }tG        |jL                         c}            }tS        ||      |D ci c]  }|jL                  | }}g }|D ]  }	 |j1                  ||           |}tW        |||||      S c c}w c c}w c c}w c c}w c c}w # tT        $ r |j1                  tI        |             Y iw xY w)z'Specialized Routine creation for Julia.r   r   r   r   r4   r\   out%drW   c                 ,    t        | j                        S rV   r   r   s    rI   r   z&JuliaCodeGen.routine.<locals>.<lambda>Z  r   rS   r   r   r,   ),r   r.   r   r   r6   r   r2   r   r7   r-   r1   r/   rb   r   r3   	enumerater   r   r   r   r   r   Oner   r   r5   r   r   r   r!   r   r   r   r   r   r;   r   r   r4   rO   r:   r   r   r   )r@   r4   r0   r   r?   r   r   r>   old_symbolsrB   rF   return_valsr   r   r   r   r   r   r   r  r  rC   rH   r  r  r  r  r  s                               rI   r	  zJuliaCodeGen.routine&  s    tZz:6N%O !677,K+K (3'8'8'=>!agg>
>  +2ceK8H "..;kI% 	A!S!qvvay5567+A		 ";/ 	GIQ$)((xx gw/ 7==!ICAEE3<!IJD$\\//F&&}VWdW['\]!'GV\+JK& (F G G ""6$V#PQxx' NN6* ""6$W!_#EF+	G0 	23$ &&w/ 	4E.3M%****+	4 &&|4 	)E#(M% 	) W#. 	3FOOM&12	3 (L( -c;/ ''		2 '',	-
 !-"*NQaff<M.MqNGN:jj+IACK+I!JK.sG<< 1991QVVQY9M9H+ ;;OOM&$9:;
  HtX{JLL] ?. "JN O ,J :
   ;OOM&$9:;s6   O,'O1
8O6O60O;'P P#P+*P+c                     g }t         t        | j                  dz  }|j                         D ]-  }|dk(  r|j	                  d       |j	                  d|z         / |S )r6  r7  rr   z#
z#   %s
r;  r<  r   r=  r   r?  s       rI   r$  zJuliaCodeGen._get_header  se    
=|| % %NN$ 	5Drz!!%(!!*t"34		5
 rS   c                     g S rV   rL   r  s     rI   r  z%JuliaCodeGen._preprocessor_statements  r  rS   c           	         g }|j                  d       g }|j                  D ]v  }t        |t              r t	        dt        t        |            z        t        |t        t        f      sJ|j                  d| j                  |j                        z         x dj                  |      }|j                  |j                  d|d       dj                  |      g}|S ).Returns the opening statements of the routine.	function z"Julia: invalid argument of type %sr  r,   r   )
rr   )r   r<   r.   r    r   r;   r  r   r5   r   r4   r:   )r@   r	  r  rb   rC   s        rI   r  z!JuliaCodeGen._get_routine_opening  s    	% $$ 	?C#~."#G#&tCy>$2 3 3#}=>D4#3#3CHH#==>	? yyw||T:;ggi(*	rS   c                     g S rV   rL   rX  s     rI   r  zJuliaCodeGen._declare_arguments  r  rS   c                     g S rV   rL   rX  s     rI   r   zJuliaCodeGen._declare_globals  r  rS   c                     g S rV   rL   rX  s     rI   r!  zJuliaCodeGen._declare_locals  r  rS   c                     g }|j                   D ]J  }t        |t              r| j                  |j                        }nt        d      |j                  |       L ddj                  |      z   dz   gS )N$unexpected object in Routine resultszreturn r,   z
end
)r=   r.   r!   r   r4   r   r   r:   )r@   r	  outsr   rF   s        rI   r#  z JuliaCodeGen._get_routine_ending  sl    oo 	F&&)$$V[[1"#IJJKKN	 DIIdO+i788rS   c                    g }g }|j                   D ]  }t        |t              r|j                  }nt	        d      | j                  dddd|j                  |      \  }}}t        |t              D ]  \  }	}
|j                  |	d|
d        t        |t              D ]5  }	t        |	t              r|	j                  }n|	}|j                  d	|z         7 |j                  d
|z          ||z   S )Nr  r   Fr   r^  r_  r   rb  r  z# unsupported: %s
ri  r=   r.   r!   r\   r   r   r0   r   r;   r   r	   r  )r@   r	  r  r%  r   r`  r   r   jl_exprr  r^   r4   s               rI   r"  zJuliaCodeGen._call_printer  s   
oo 	2F&&)"--	"#IJJ040R0RUe<fkkU^ 1S 1`-I}g !4 ,Q###&*,, m5 4c8,88DD##)T244 f01'	2( j((rS   c                 @    t        ddd      }|j                  |      S )NFr  )r   r   )r@   r   ps      rI   r   zJuliaCodeGen._indent_code  s"     u>?}}Y''rS   c                 .    | j                  |||||       y rV   rn  ro  s         rI   dump_jlzJuliaCodeGen.dump_jl  rq  rS   r  r'  )rN   rd   re   rf   r|  rJ   r	  r$  r  r  r  r   r!  r#  r"  r   r  r  r"   r&  r  r~  r  s   @rI   r%   r%     st     N5YMv
&	9)2(; 'G''//GO yHrS   r%   c                        e Zd ZdZdZd fd	Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zd Zd ZddZee_        ej&                  j                  e_        egZ xZS )r&   a  Generator for Octave code.

    The .write() method inherited from CodeGen will output a code file
    <prefix>.m.

    Octave .m files usually contain one function.  That function name should
    match the filename (``prefix``).  If you pass multiple ``name_expr`` pairs,
    the latter ones are presumed to be private functions accessed by the
    primary function.

    You should only pass inputs to ``argument_sequence``: outputs are ordered
    according to their order in ``name_expr``.

    r  c                 J    t         |   |       |xs
 t               | _        y rV   )r1  rJ   r   r   r  s      rI   rJ   zOctaveCodeGen.__init__  s     !5"3"5rS   c           
      n   t        |      r,t        |t        t        f      s|st	        d      t        | }nt        |      }|j                  t              D ch c]  }|j                   }}|
t               n
t        |      }|j                  |z
  |z
  }t               }	|D ]]  }
t        |
t              r)|	j                  |
j                  d   j                         <t        |
t              rM|	j                  |
       _ g }t        |      D ]  \  }}t        |t               r|j"                  }|j$                  }|}t        |t              r|j&                  j                  }t        |t        t(        t*        f      st-        d      |j/                  t1        |||             |j3                  |      r|	j5                  |       |j/                  t1        |d|dz   z                g }i }|j                  t              D ]  }|||j&                  j                  <    |j                  t*              D ]  }|||<   	 t7        |	t8              D ]  }|j/                  t;        |              |g }|D ]?  }t        |t<              r|j/                  |j                         /|j/                  |       A |}|D cg c]  }|j>                  |vs| }}|rOd}|jA                  d	jC                  |D cg c]  }t9        |j>                         c}            }tE        ||      |D ci c]  }|j>                  | }}g }|D ]  }	 |j/                  ||           |}tI        |||||      S c c}w c c}w c c}w c c}w # tF        $ r |j/                  t;        |             Y dw xY w)
z(Specialized Routine creation for Octave.r   r   r   r  r  rW   r   r   r,   )%r   r.   r   r   r6   r   r2   r   r7   r-   r1   r/   rb   r   r3   r  r   r   r   r   r   r   r   r   r!   r   r   r   r;   r   r   r4   rO   r:   r   r   r   )r@   r4   r0   r   r?   r   r   r>   r  rB   rF   r  r   r   r   r   r  r  rC   rH   r  r  r  r  r  s                            rI   r	  zOctaveCodeGen.routine  s{    tZz:6N%O !677,K+K (3'8'8'=>!agg>
>  +2ceK8H "..;kI% 	A!S!qvvay5567+A		 ";/ 	GIQ$)((xx gw/$\\//F!'GV\+JK& (F G G ""6$V#PQxx' NN6* ""6$W!_#EF'	G,  &&w/ 	4E.3M%****+	4 &&|4 	)E#(M% 	) W#. 	3FOOM&12	3 (L( -c;/ ''		2 '',	-
 !-"*NQaff<M.MqNGN:jj+IACK+I!JK.sG<< 1991QVVQY9M9H+ ;;OOM&$9:;
  HtX{JLLU ?t O ,J :
   ;OOM&$9:;s0   M:M?M?>N5N	N#N43N4c                     g }t         t        | j                  dz  }|j                         D ]-  }|dk(  r|j	                  d       |j	                  d|z         / |S )r6  r7  rr   z%
z%%   %s
r  r?  s       rI   r$  zOctaveCodeGen._get_headerQ  se    
=|| % %NN$ 	6Drz!!%(!!+"45		6
 rS   c                     g S rV   rL   r  s     rI   r  z&OctaveCodeGen._preprocessor_statements]  r  rS   c           	      D   g }|j                  d       g }|j                  D ]J  }t        |t              r| j	                  |j
                        }nt        d      |j                  |       L t        |      dkD  r'|j                  ddj                  |      z   dz          n |j                  dj                  |             |j                  d       g }|j                  D ]v  }t        |t        t        f      r t        d	t        t        |            z        t        |t              sJ|j                  d
| j	                  |j
                        z         x dj                  |      }|j                  |j
                  d|d       dj                  |      g}|S )r  r  r  r   [r,   ]rr   rb  z#Octave: invalid argument of type %sr  r   r  )r   r=   r.   r!   r   r4   r   rG  r:   r<   r    r5   r;   r  r   )r@   r	  r  r  r   rF   rb   rC   s           rI   r  z"OctaveCodeGen._get_routine_opening`  sg   	% oo 	F&&)$$V[[1"#IJJKKN	 t9q=SDIIdO4s:;RWWT]+ $$ 	?C#>?"#H#&tCy>$2 3 3#}-D4#3#3CHH#==>	? yyw||T:;ggi(*	rS   c                     g S rV   rL   rX  s     rI   r  z OctaveCodeGen._declare_arguments  r  rS   c           
          |j                   sg S dj                  t        |j                   D cg c]  }| j                  |       c}            }d|z   dz   gS c c}w )NrF  zglobal r  )r?   r:   r   r   )r@   r	  grF   s       rI   r   zOctaveCodeGen._declare_globals  sW    ""IHHV':M:MNQT--a0NOPA$%% Os   Ac                     g S rV   rL   rX  s     rI   r!  zOctaveCodeGen._declare_locals  r  rS   c                     dgS )Nzend
rL   rX  s     rI   r#  z!OctaveCodeGen._get_routine_ending  s
    yrS   c           	         g }g }|j                   D ]  }t        |t              r|j                  }nt	        d      | j                  dddd|j                  |      \  }}}t        |t              D ]  \  }	}
|j                  d|	d|
d	        t        |t              D ]5  }	t        |	t              r|	j                  }n|	}|j                  d
|z         7 |j                  d|z          ||z   S )Nr  r   Fr  r_  r   z  rb  z;  % constant
z  %% unsupported: %s
ri  r  )r@   r	  r  r%  r   r`  r   r   oct_exprr  r^   r4   s               rI   r"  zOctaveCodeGen._call_printer  s   
oo 	3F&&)"--	"#IJJ151S1SUe<fkkU^ 2T 2`.I}h !4 <Q##36:<< m5 7c8,88DD##,577 f12'	3( j((rS   c                 .    | j                  dddd|      S )Nr   Fr  r  r   s     rI   r   zOctaveCodeGen._indent_code  s#    11Ue<iI 	IrS   c                    | j                  |      }t        |      D ]x  \  }}	|dkD  r|r|j                  d       |j                  | j	                  |	             |dk(  ro|	j
                  |k7  rt        d      |rS|j                  d|j                         z   dz          |j                  dj                  | j                                      |j                  | j                  |	             |j                  | j                  |	             |j                  | j                  |	             |r|j                  d       |j                  | j                  |	             |r|j                  d       |j                  | j                  |	             { | j                  dj                  |            }|r|j!                  |       y y )Nr   r  z(Octave function name should match prefix%z  Autogenerated by SymPy
rr   )r  r  r   ra   r  r4   r6   r   r:   r$  r  r   r!  r"  r#  r   r  )
r@   r  r  r  r  r  inliner%  r   r	  s
             rI   dump_mzOctaveCodeGen.dump_m  s    226:
#H- 	AJAw1u%%d+d77@AAv<<6)$%OPP%%cFLLN&:&B'C D%%bggd.>.>.@&ABd55g>?d33G<=d227;<!!$'d009:!!$'d66w?@)	A, &&rwwz':;
GGJ rS   r  )TTT)rN   rd   re   rf   r|  rJ   r	  r$  r  r  r  r   r!  r#  r"  r   r  r  r"   r&  r  r~  r  s   @rI   r&   r&     sw     N6XMt
 D&)2I @ &F&&..FN xHrS   r&   c                        e Zd ZdZdZd fd	Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zd Zd ZddZee_        ej&                  j                  e_        egZ xZS )r'   zvGenerator for Rust code.

    The .write() method inherited from CodeGen will output a code file
    <prefix>.rs

    rsc                 L    t         |   |       |xs
 t               | _        y )N)r   )r1  rJ   r   r   r  s      rI   rJ   zRustCodeGen.__init__  s"    )3/"3rS   c           
         t        |      r,t        |t        t        f      s|st	        d      t        | }nt        |      }|j                  t              D ch c]  }|j                   }}|
t               n
t        |      }|j                  |z
  |z
  |j                  t              z
  }g }	g }
t        |      D ]1  \  }}t        |t              r|j                  }|j                  }|}t        |t              rgt!        |j"                  D cg c]  }t$        j&                  |f c}      }|j(                  j                  }|
j+                  t-        ||||             t        |t        t.        t0        f      st3        d      |	j+                  t5        |||             |j7                  |      r|j9                  |       |	j+                  t5        |d|dz   z               4 |
j;                  d 	       t=        |
      }i }|j                  t              D ]  }|||j(                  j                  <    |j                  t0              D ]  }|||<   	 t?        |t@        	      D ]  }|j+                  tC        |              |g }|D ]?  }t        |tD              r|j+                  |j                         /|j+                  |       A |}|D cg c]  }|jF                  |vs| }}|rOd
}|jI                  djK                  |D cg c]  }tA        |jF                         c}            }tM        ||      |D ci c]  }|jF                  | }}g }|D ]  }	 |j+                  ||           |}tQ        |||	||      S c c}w c c}w c c}w c c}w c c}w # tN        $ r |j+                  tC        |             Y iw xY w)z&Specialized Routine creation for Rust.r   r   r   r  r  r   rW   c                 ,    t        | j                        S rV   r   r   s    rI   r   z%RustCodeGen.routine.<locals>.<lambda>  r   rS   r   r   r,   ))r   r.   r   r   r6   r   r2   r   r7   r-   r1   r   r  r   r   r   r   r   r   r  r   r   r5   r   r   r   r!   r   r   r   r   r   r;   r   r   r4   rO   r:   r   r   r   )r@   r4   r0   r   r?   r   r   r>   rB   r  r   r   r   r   r   r   r   r  r  rC   rH   r  r  r  r  r  s                             rI   r	  zRustCodeGen.routine  s    tZz:6N%O !677,K+K (3'8'8'=>!agg>
>  +2ceK8H **Z7+EHYHYZaHbb ";/ 	GIQ$)((xx gw/ 7==!ICAEE3<!IJD$\\//F&&}VWdW['\]!'GV\+JK& (F G G ""6$V#PQxx' NN6* ""6$W!_#EF+	G0 	23$ &&w/ 	4E.3M%****+	4 &&|4 	)E#(M% 	) W#. 	3FOOM&12	3 (L( -c;/ ''		2 '',	-
 !-"*NQaff<M.MqNGN:jj+IACK+I!JK.sG<< 1991QVVQY9M9H+ ;;OOM&$9:;
  HtX{JLLQ ?" "JN O ,J :
   ;OOM&$9:;s6   NN
"N 6N N%N*/N//#OOc                    g }|j                  d       t        t        | j                  dz  }|j	                         D ]6  }|j                  d|j                  d      z  j                         dz          8 |j                  d       |S )r6  z/*
r7  z *%sr9  r  z */
)r   r;  r<  r   r=  r>  rstripr?  s       rI   r$  zRustCodeGen._get_header9  s    
&!=+/<< 9 9NN$ 	JDvB7??ADHI	J'"rS   c                    |j                   D cg c]  }|j                  d       }}t        |      dk(  r	d|d   z   }n2t        |j                         dkD  rddj                  |      z   dz   }nd}g }|j                  D ]  }| j
                  j                  |j                        }|j                  st        |t              r&|j                  d	|z  |j                  d      f       j|j                  ||j                  d      f        dj                  |D cg c]  }d
|z  	 c}      }	d|j                  d|	d|S c c}w c c}w )rC  Rustr   z -> r   z -> (r,   r   rr   rE  z%s: %szfn r   )r=   r   rG  r:   r<   r   r   r4   r   r.   r   r   )
r@   r	  r   r=   rstyperI  rC   r4   rJ  r<   s
             rI   rK  zRustCodeGen.get_prototypeD  s,    4;??Ca1>>&)CCw<1gaj(F!A%tyy11C7FF	$$ 	CC<<''1D~~C!<  %$,0@0@0H!IJ  $(8(8(@!AB	C IIi@1@A	 'i@@# D  As   EE
c                 
    g }|S rV   rL   )r@   r  r%  s      rI   r  z$RustCodeGen._preprocessor_statements`  s    
rS   c                 0    | j                  |      }d|z  gS rR  rS  rT  s      rI   r  z RustCodeGen._get_routine_openinge  rV  rS   c                     g S rV   rL   rX  s     rI   r  zRustCodeGen._declare_argumentsi  rY  rS   c                     g S rV   rL   rX  s     rI   r   zRustCodeGen._declare_globalsm  rY  rS   c                     g S rV   rL   rX  s     rI   r!  zRustCodeGen._declare_localsq  rY  rS   c           	      J   g }g }g }g }|j                   D ];  }t        |t              s|j                  r!|j	                  |j
                         = |j                  D ]  }t        |t              r1|j                  }|j	                  t        |j                               nt        d      | j                  dddd|j                  |      \  }	}
}t        |	t              D ]  \  }}|j	                  d|d|d	        t        |
t              D ]5  }t        |t              r|j                  }n|}|j	                  d
|z         7 |j	                  d|z          t!        |      dkD  rddj#                  |      z   dz   g}|j	                  d       ||z   |z   S )Nr  r   Fr  r_  r   zconst z: f64 = rc  z// unsupported: %s
zlet %s
r   r   r,   r   r  )r<   r.   r   r   r   r4   r=   r!   r\   r;   r   r   r0   r   r	   r  rG  r:   )r@   r	  r%  r  returnsr]  rC   r   r`  r   r   rs_exprr4   rf  r  s                  rI   r"  zRustCodeGen._call_printeru  s   

 $$ 	-C#z*3>>""388,	- oo 	5F&&)"--	s6#4#456"#IJJ040R0RUe<fkkU^ 1S 1`-I}g  &iS9 Me##tU$KLM m5 Ec8,88DD##$:d$CDE j723)	5, w<!TYYw//#56Gtj(722rS   c                     dgS rk  rL   rX  s     rI   r#  zRustCodeGen._get_routine_ending  rl  rS   c                 .    | j                  |||||       y rV   rn  ro  s         rI   dump_rszRustCodeGen.dump_rs  rq  rS   r  r'  )rN   rd   re   rf   r|  rJ   r	  r$  rK  r  r  r  r   r!  r"  r#  r  r  r"   r&  r  r~  r  s   @rI   r'   r'     sv     N4SMl	A8
&)3V; 'G''//GO yHrS   r'   c                     | dk(  r.|n+|j                         dk(  rd} n|j                         dk(  rd} t        t        t        t        t
        t        t        dj                  | j                               }|t        d| z         |||      S )Nr   c89r  r/  r  )r   r  r  F95r   r   r   zLanguage '%s' is not supported.)r3  r#   r  r  r$   r%   r&   r'   getr   r6   )r   r   r2  r   CodeGenClasss        rI   get_code_generatorr    s    3^^&H^^&H!*Z#l+') *-X^^-=)>  :XEFF))rS   c           	         ||
&t        d      |
t        d      t        |||	|      }
t        | d   t              r| g} || d   d   }g }| D ](  \  }}|j	                  |
j                  ||||             * |
j                  |||||      S )a  Generate source code for expressions in a given language.

    Parameters
    ==========

    name_expr : tuple, or list of tuples
        A single (name, expression) tuple or a list of (name, expression)
        tuples.  Each tuple corresponds to a routine.  If the expression is
        an equality (an instance of class Equality) the left hand side is
        considered an output argument.  If expression is an iterable, then
        the routine will have multiple outputs.

    language : string,
        A string that indicates the source code language.  This is case
        insensitive.  Currently, 'C', 'F95' and 'Octave' are supported.
        'Octave' generates code compatible with both Octave and Matlab.

    prefix : string, optional
        A prefix for the names of the files that contain the source code.
        Language-dependent suffixes will be appended.  If omitted, the name
        of the first name_expr tuple is used.

    project : string, optional
        A project name, used for making unique preprocessor instructions.
        [default: "project"]

    to_files : bool, optional
        When True, the code will be written to one or more files with the
        given prefix, otherwise strings with the names and contents of
        these files are returned. [default: False]

    header : bool, optional
        When True, a header is written on top of each source file.
        [default: True]

    empty : bool, optional
        When True, empty lines are used to structure the code.
        [default: True]

    argument_sequence : iterable, optional
        Sequence of arguments for the routine in a preferred order.  A
        CodeGenError is raised if required arguments are missing.
        Redundant arguments are used without warning.  If omitted,
        arguments will be ordered alphabetically, but with all input
        arguments first, and then output or in-out arguments.

    global_vars : iterable, optional
        Sequence of global variables used by the routine.  Variables
        listed here will not show up as function arguments.

    standard : string, optional

    code_gen : CodeGen instance, optional
        An instance of a CodeGen subclass. Overrides ``language``.

    printer : Printer instance, optional
        An instance of a Printer subclass.

    Examples
    ========

    >>> from sympy.utilities.codegen import codegen
    >>> from sympy.abc import x, y, z
    >>> [(c_name, c_code), (h_name, c_header)] = codegen(
    ...     ("f", x+y*z), "C89", "test", header=False, empty=False)
    >>> print(c_name)
    test.c
    >>> print(c_code)
    #include "test.h"
    #include <math.h>
    double f(double x, double y, double z) {
       double f_result;
       f_result = x + y*z;
       return f_result;
    }
    <BLANKLINE>
    >>> print(h_name)
    test.h
    >>> print(c_header)
    #ifndef PROJECT__TEST__H
    #define PROJECT__TEST__H
    double f(double x, double y, double z);
    #endif
    <BLANKLINE>

    Another example using Equality objects to give named outputs.  Here the
    filename (prefix) is taken from the first (name, expr) pair.

    >>> from sympy.abc import f, g
    >>> from sympy import Eq
    >>> [(c_name, c_code), (h_name, c_header)] = codegen(
    ...      [("myfcn", x + y), ("fcn2", [Eq(f, 2*x), Eq(g, y)])],
    ...      "C99", header=False, empty=False)
    >>> print(c_name)
    myfcn.c
    >>> print(c_code)
    #include "myfcn.h"
    #include <math.h>
    double myfcn(double x, double y) {
       double myfcn_result;
       myfcn_result = x + y;
       return myfcn_result;
    }
    void fcn2(double x, double y, double *f, double *g) {
       (*f) = 2*x;
       (*g) = y;
    }
    <BLANKLINE>

    If the generated function(s) will be part of a larger project where various
    global variables have been defined, the 'global_vars' option can be used
    to remove the specified variables from the function signature

    >>> from sympy.utilities.codegen import codegen
    >>> from sympy.abc import x, y, z
    >>> [(f_name, f_code), header] = codegen(
    ...     ("f", x+y*z), "F95", header=False, empty=False,
    ...     argument_sequence=(x, y), global_vars=(z,))
    >>> print(f_code)
    REAL*8 function f(x, y)
    implicit none
    REAL*8, intent(in) :: x
    REAL*8, intent(in) :: y
    f = x + y*z
    end function
    <BLANKLINE>

    z Need either language or code_genz.You cannot specify both language and code_gen.r   )r6   r  r.   r;   r   r	  r  )	name_exprr   r  r   r  r  r  r   r?   r2  code_genr   r  r4   r0   s                  rI   r(   r(     s    J ?@@MNN%h7K)A,$K	~1a H 7
d((t5F)46 	77
 >>(FHfeDDrS   c                 @    t        |      }|j                  | |||      S )a  A factory that makes an appropriate Routine from an expression.

    Parameters
    ==========

    name : string
        The name of this routine in the generated code.

    expr : expression or list/tuple of expressions
        A SymPy expression that the Routine instance will represent.  If
        given a list or tuple of expressions, the routine will be
        considered to have multiple return values and/or output arguments.

    argument_sequence : list or tuple, optional
        List arguments for the routine in a preferred order.  If omitted,
        the results are language dependent, for example, alphabetical order
        or in the same order as the given expressions.

    global_vars : iterable, optional
        Sequence of global variables used by the routine.  Variables
        listed here will not show up as function arguments.

    language : string, optional
        Specify a target language.  The Routine itself should be
        language-agnostic but the precise way one is created, error
        checking, etc depend on the language.  [default: "F95"].

    Notes
    =====

    A decision about whether to use output arguments or return values is made
    depending on both the language and the particular mathematical expressions.
    For an expression of type Equality, the left hand side is typically made
    into an OutputArgument (or perhaps an InOutArgument if appropriate).
    Otherwise, typically, the calculated expression is made a return values of
    the routine.

    Examples
    ========

    >>> from sympy.utilities.codegen import make_routine
    >>> from sympy.abc import x, y, f, g
    >>> from sympy import Eq
    >>> r = make_routine('test', [Eq(f, 2*x), Eq(g, x + y)])
    >>> [arg.result_var for arg in r.results]
    []
    >>> [arg.name for arg in r.arguments]
    [x, y, f, g]
    >>> [arg.name for arg in r.result_variables]
    [f, g]
    >>> r.local_vars
    set()

    Another more complicated example with a mixture of specified and
    automatically-assigned names.  Also has Matrix output.

    >>> from sympy import Matrix
    >>> r = make_routine('fcn', [x*y, Eq(f, 1), Eq(g, x + g), Matrix([[x, 2]])])
    >>> [arg.result_var for arg in r.results]  # doctest: +SKIP
    [result_5397460570204848505]
    >>> [arg.expr for arg in r.results]
    [x*y]
    >>> [arg.name for arg in r.arguments]  # doctest: +SKIP
    [x, y, f, g, out_8598435338387848786]

    We can examine the various arguments more closely:

    >>> from sympy.utilities.codegen import (InputArgument, OutputArgument,
    ...                                      InOutArgument)
    >>> [a.name for a in r.arguments if isinstance(a, InputArgument)]
    [x, y]

    >>> [a.name for a in r.arguments if isinstance(a, OutputArgument)]  # doctest: +SKIP
    [f, out_8598435338387848786]
    >>> [a.expr for a in r.arguments if isinstance(a, OutputArgument)]
    [1, Matrix([[x, 2]])]

    >>> [a.name for a in r.arguments if isinstance(a, InOutArgument)]
    [g]
    >>> [a.expr for a in r.arguments if isinstance(a, InOutArgument)]
    [g + x]

    )r  r	  )r4   r0   r   r?   r   r  s         rI   r)   r)   d  s'    n "(+HD$(9;GGrS   rV   r   )NNr   FTTNNNNN)NNr  )Crf   rM  r  ior   sympyr   r<  
sympy.corer   r   r   r   r	   r
   sympy.printing.cr   sympy.printing.codeprinterr   sympy.printing.fortranr   sympy.printing.juliar   sympy.printing.octaver   sympy.printing.rustr   sympy.tensorr   r   r   sympy.matricesr   r   r   r   r   sympy.utilities.iterablesr   __all__r   r   r   ry   r   r   r   r   r   r    r5   r!   r"   	Exceptionr   r   r;  r#   r  r  r$   r%   r&   r'   r  r(   r)   rL   rS   rI   <module>r     s  Ob 
   . B B , 6 / 1 3 / 2 25 5 1	"s sl  E;r2u=h'2r5A,	2r7K  .2K/ K/\	x 		H 	 &+Xz +\Hj $HXz H^r  r j		9 	y Z w Z x  T"w T"nF7 FRrG rhV' Vv*, <EGKDH[E| 04,1YHrS   