o
    8VavX                     @   s   d Z ddlmZmZ ddlmZmZmZmZ ddl	m
Z
 ddlmZ ddlmZmZ ddlmZ g dZd	d
ddddddZG dd deZdddZdd ZdS )a  
Julia code printer

The `JuliaCodePrinter` converts SymPy expressions into Julia expressions.

A complete code generator, which uses `julia_code` extensively, can be found
in `sympy.utilities.codegen`.  The `codegen` module can be used to generate
complete source code files.

    )AnyDict)MulPowSRational)_keep_coeff)CodePrinter)
precedence
PRECEDENCEsearch)3ZsinZcosZtanZcotZsecZcscZasinZacosZatanZacotZasecZacscZsinhZcoshZtanhZcothZsechZcschZasinhZacoshZatanhZacothZasechZacschZsincZatan2signZfloorlogexpZcbrtsqrtZerfZerfcZerfiZ	factorialZgammaZdigammaZtrigammaZ	polygammaZbetaZairyaiZairyaiprimeZairybiZairybiprimebesseljbesselyZbesseliZbesselkZerfinvZerfcinvabsZceilZconjZhankelh1Zhankelh2imagreal)ZAbsZceiling	conjugateZhankel1Zhankel2imrec                	       s  e Zd ZdZdZdZddddZdd	d
i dddddZi f fdd	Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Z fd&d'Zd(d) Z fd*d+Z fd,d-Z fd.d/Z fd0d1Zd2d3 Zd4d5 Zd6d7 Zd8d9 Zd:d; Zd<d= ZeZ d>d? Z!d@dA Z"dBdC Z#dDdE Z$dFdG Z%dHdI Z&dJdK Z'dLdM Z(dNdO Z)dPdQ Z*dRdS Z+dTdU Z,dVdW Z-dXdY Z.dZd[ Z/d\d] Z0  Z1S )^JuliaCodePrinterzD
    A printer to convert expressions to strings of Julia code.
    Z_juliaZJuliaz&&z||!)andornotNauto   TF)orderZ	full_precZ	precisionuser_functionsZhumanZallow_unknown_functionscontractinlinec                    sH   t  | tttt| _| jtt |di }| j| d S )Nr"   )	super__init__dictzipknown_fcns_src1Zknown_functionsupdateknown_fcns_src2get)selfsettingsZ	userfuncs	__class__ 6/usr/lib/python3/dist-packages/sympy/printing/julia.pyr&   I   s
   zJuliaCodePrinter.__init__c                 C   s   |d S )N   r1   )r-   pr1   r1   r2   _rate_index_positionQ      z%JuliaCodePrinter._rate_index_positionc                 C   s   d| S )N%sr1   )r-   Z
codestringr1   r1   r2   _get_statementU   r6   zJuliaCodePrinter._get_statementc                 C   s
   d |S )Nz# {}format)r-   textr1   r1   r2   _get_commentY      
zJuliaCodePrinter._get_commentc                 C   s   d ||S )Nzconst {} = {}r9   )r-   namevaluer1   r1   r2   _declare_number_const]      z&JuliaCodePrinter._declare_number_constc                 C   s
   |  |S N)indent_code)r-   linesr1   r1   r2   _format_codea   r=   zJuliaCodePrinter._format_codec                    s    |j \ } fddt|D S )Nc                 3   s&    | ]}t  D ]}||fV  qqd S rB   )range).0jirowsr1   r2   	<genexpr>h   s   $ z<JuliaCodePrinter._traverse_matrix_indices.<locals>.<genexpr>)shaperF   )r-   Zmatcolsr1   rJ   r2   _traverse_matrix_indicese   s   
z)JuliaCodePrinter._traverse_matrix_indicesc                 C   s^   g }g }|D ]$}t | j|j|jd |jd g\}}}|d|||f  |d q||fS )N   zfor %s = %s:%send)map_printlabellowerupperappend)r-   indicesZ
open_linesZclose_linesrI   varstartstopr1   r1   r2   _get_loop_opening_endingk   s   
z)JuliaCodePrinter._get_loop_opening_endingc                    sd  |j r|jr| d jrdtj |  S t| | \}}|dk r/t| |}d}nd}g }g }g }j	dvrA|
 }nt|}|D ]l}	|	jr|	jr|	jjr|	jjr|	jdkrk|t|	j|	j dd qHt|	jd jd	krt|	jtr||	 |t|	j|	j  qH|	jr|	tjur|	jd	kr|t|	j |	jd	kr|t|	j qH||	 qH|ptjg} fd
d|D }
 fdd|D }|D ]}	|	j|v rd|||	j  |||	j< qdd }|s||||
 S t|d	kr|d j rdnd}||||
 | |d  S tdd |D r dnd}||||
 | d|||  S )Nr   z%sim- )oldZnoneF)ZevaluaterP   c                       g | ]} | qS r1   parenthesizerG   xZprecr-   r1   r2   
<listcomp>       z/JuliaCodePrinter._print_Mul.<locals>.<listcomp>c                    ra   r1   rb   rd   rf   r1   r2   rg      rh   (%s)c                 S   sF   |d }t dt| D ]}| |d  jrdnd}|| ||  }q|S )Nr   rP   *.*)rF   len	is_number)aa_strrrI   Zmulsymr1   r1   r2   multjoin   s
   z-JuliaCodePrinter._print_Mul.<locals>.multjoin/./c                 S      g | ]}|j qS r1   rm   )rG   Zbir1   r1   r2   rg          )rm   Zis_imaginaryZas_coeff_Mul
is_integerrS   r   ZImaginaryUnitr
   r   r!   Zas_ordered_factorsr   Z	make_argsis_commutativeZis_Powr   Zis_RationalZis_negativerW   r   baserl   args
isinstanceZInfinityr4   r   qOneindexall)r-   exprcer   rn   bZ	pow_parenrz   itemro   Zb_strrq   Zdivsymr1   rf   r2   
_print_Mulw   sf   



 



 zJuliaCodePrinter._print_Mulc                 C   s,   |  |j}|  |j}|j}d|||S )Nz{} {} {})rS   lhsrhsZrel_opr:   )r-   r   lhs_coderhs_codeopr1   r1   r2   _print_Relational   s   z"JuliaCodePrinter._print_Relationalc                 C   s   t dd |jD rdnd}t|}|jtjkr d| |j S |jrZ|jtj kr>|jj	r0dnd}d| d| |j  S |jtj
 krZ|jj	rKdnd}d| d	| |j|  S d
| |j||| |j|f S )Nc                 S   rt   r1   ru   rd   r1   r1   r2   rg      rv   z/JuliaCodePrinter._print_Pow.<locals>.<listcomp>^z.^zsqrt(%s)rr   rs   1r7   z%s%s%s)r   rz   r
   r   r   HalfrS   ry   rx   rm   r}   rc   )r-   r   Z	powsymbolPRECZsymr1   r1   r2   
_print_Pow   s   zJuliaCodePrinter._print_Powc                 C   s(   t |}d| |j|| |j|f S )Nz%s^%s)r
   rc   ry   r   r-   r   r   r1   r1   r2   _print_MatPow   s   zJuliaCodePrinter._print_MatPowc                       | j d rdS t |S )Nr$   Zpi	_settingsr%   Z_print_NumberSymbolr-   r   r/   r1   r2   	_print_Pi      
zJuliaCodePrinter._print_Pic                 C      dS )Nr   r1   r   r1   r1   r2   _print_ImaginaryUnit      z%JuliaCodePrinter._print_ImaginaryUnitc                    r   )Nr$   r   r   r   r/   r1   r2   _print_Exp1   r   zJuliaCodePrinter._print_Exp1c                    r   )Nr$   Z
eulergammar   r   r/   r1   r2   _print_EulerGamma   r   z"JuliaCodePrinter._print_EulerGammac                    r   )Nr$   catalanr   r   r/   r1   r2   _print_Catalan   r   zJuliaCodePrinter._print_Catalanc                    r   )Nr$   Zgoldenr   r   r/   r1   r2   _print_GoldenRatio  r   z#JuliaCodePrinter._print_GoldenRatioc                 C   s   ddl m} ddlm} ddlm} |j}|j}| jd sHt	|j|rHg }g }|j
D ]\}	}
||||	 ||
 q*|t|| }| |S | jd r]||sW||r]| ||S | |}| |}| d||f S )Nr   )
Assignment)	Piecewise)IndexedBaser$   r#   z%s = %s)Zsympy.codegen.astr   Z$sympy.functions.elementary.piecewiser   Zsympy.tensor.indexedr   r   r   r   r{   rz   rW   r(   rS   ZhasZ_doprint_loopsr8   )r-   r   r   r   r   r   r   ZexpressionsZ
conditionsr   r   Ztempr   r   r1   r1   r2   _print_Assignment  s(   


z"JuliaCodePrinter._print_Assignmentc                 C   r   )NZInfr1   r   r1   r1   r2   _print_Infinity%  r   z JuliaCodePrinter._print_Infinityc                 C   r   )Nz-Infr1   r   r1   r1   r2   _print_NegativeInfinity)  r   z(JuliaCodePrinter._print_NegativeInfinityc                 C   r   )NZNaNr1   r   r1   r1   r2   
_print_NaN-  r   zJuliaCodePrinter._print_NaNc                    s    dd  fdd|D  d S )NzAny[, c                 3   s    | ]}  |V  qd S rB   rS   rG   rn   r-   r1   r2   rL   2  s    z/JuliaCodePrinter._print_list.<locals>.<genexpr>])joinr   r1   r   r2   _print_list1  s    zJuliaCodePrinter._print_listc                 C   s.   t |dkrd| |d  S d| |d S )NrP   z(%s,)r   ri   r   )rl   rS   Z	stringifyr   r1   r1   r2   _print_tuple5  s   zJuliaCodePrinter._print_tuplec                 C   r   )Ntruer1   r   r1   r1   r2   _print_BooleanTrue=  r   z#JuliaCodePrinter._print_BooleanTruec                 C   r   )NZfalser1   r   r1   r1   r2   _print_BooleanFalseA  r   z$JuliaCodePrinter._print_BooleanFalsec                 C   s   t | S rB   )strrU   r   r1   r1   r2   _print_boolE  rA   zJuliaCodePrinter._print_boolc                    s   |j dks
|jdkrd|j |jf S |j |jfdkr d|d  S |j dkr0d|j dddd	 S |jdkrCdd
 fdd|D  S d|j ddddd S )Nr   zzeros(%s, %s))rP   rP   z[%s])r   r   rP   r^    )rowstartrowendcolsepr   c                       g | ]}  |qS r1   r   r   r   r1   r2   rg   W      z6JuliaCodePrinter._print_MatrixBase.<locals>.<listcomp>z;
)r   r   Zrowsepr   )rK   rN   tabler   )r-   Ar1   r   r2   _print_MatrixBaseM  s   

z"JuliaCodePrinter._print_MatrixBasec                 C   sr   ddl m} | }|dd |D }|dd |D }|dd |D }d| || || ||j|jf S )Nr   )Matrixc                 S   s   g | ]}|d  d qS )r   rP   r1   rG   kr1   r1   r2   rg   `  rh   z8JuliaCodePrinter._print_SparseMatrix.<locals>.<listcomp>c                 S   s   g | ]}|d  d  qS )rP   r1   r   r1   r1   r2   rg   a  rh   c                 S   s   g | ]}|d  qS )   r1   r   r1   r1   r2   rg   b  s    zsparse(%s, %s, %s, %s, %s))Zsympy.matricesr   Zcol_listrS   rK   rN   )r-   r   r   LIJZAIJr1   r1   r2   _print_SparseMatrix\  s   z$JuliaCodePrinter._print_SparseMatrixc                 C   s.   | j |jtd ddd|jd |jd f  S )NZAtomT)strictz[%s,%s]rP   )rc   parentr   rI   rH   r   r1   r1   r2   _print_MatrixElementg  s   z%JuliaCodePrinter._print_MatrixElementc                    sL    fdd}  |jd ||j|jjd  d ||j|jjd  d S )Nc                    s   | d d }| d }| d }  |}||krdn  |}|dkr8|dkr,||kr,dS ||kr2|S |d | S d|  ||fS )Nr   rP   r   rQ   :)rS   r   )re   ZlimlhstepZlstrZhstrr   r1   r2   strslicem  s   
z5JuliaCodePrinter._print_MatrixSlice.<locals>.strslice[r   ,rP   r   )rS   r   ZrowslicerM   Zcolslice)r-   r   r   r1   r   r2   _print_MatrixSlicel  s   z#JuliaCodePrinter._print_MatrixSlicec                    s0    fdd|j D }d |jjd|f S )Nc                    r   r1   r   )rG   rI   r   r1   r2   rg     r   z3JuliaCodePrinter._print_Indexed.<locals>.<listcomp>z%s[%s]r   )rX   rS   ry   rT   r   )r-   r   Zindsr1   r   r2   _print_Indexed  s   zJuliaCodePrinter._print_Indexedc                 C   s   |  |jS rB   )rS   rT   r   r1   r1   r2   
_print_Idx  rA   zJuliaCodePrinter._print_Idxc                 C   s   d|  |jd  S )Nzeye(%s)r   )rS   rM   r   r1   r1   r2   _print_Identity  s   z JuliaCodePrinter._print_Identityc                    s   d  fdd jD S )Nrk   c                    s   g | ]
} |t qS r1   )rc   r
   )rG   argr   r-   r1   r2   rg     s    z;JuliaCodePrinter._print_HadamardProduct.<locals>.<listcomp>)r   rz   r   r1   r   r2   _print_HadamardProduct  s   z'JuliaCodePrinter._print_HadamardProductc                 C   s*   t |}d| |j|| |j|gS )Nz.**)r
   r   rc   ry   r   r   r1   r1   r2   _print_HadamardPower  s
   z%JuliaCodePrinter._print_HadamardPowerc                 C   D   ddl m}m} |j}|tjd|  ||jtj | }| |S )Nr   )r   r   r   )	sympy.functionsr   r   argumentr   Pir!   r   rS   )r-   r   r   r   re   expr2r1   r1   r2   	_print_jn     $
zJuliaCodePrinter._print_jnc                 C   r   )Nr   )r   r   r   )	r   r   r   r   r   r   r!   r   rS   )r-   r   r   r   re   r   r1   r1   r2   	_print_yn  r   zJuliaCodePrinter._print_ync           
         s  |j d jdkrtdg } jd r9 fdd|j d d D }d |j d j }d|| }d	| d
 S t|j D ]J\}\}}|dkrS|d |  n|t	|j d krf|dkrf|d n
|d |   |}	||	 |t	|j d kr|d q>d|S )Nr`   TzAll Piecewise expressions must contain an (expr, True) statement to be used as a default condition. Without one, the generated expression may not evaluate to anything under some condition.r$   c                    s(   g | ]\}}d   | |qS )z({}) ? ({}) :)r:   rS   )rG   r   r   r   r1   r2   rg     s
    z5JuliaCodePrinter._print_Piecewise.<locals>.<listcomp>z (%s)
()r   zif (%s)rP   elsezelseif (%s)rQ   )
rz   Zcond
ValueErrorr   rS   r   r   	enumeraterW   rl   )
r-   r   rD   ZecpairsZelastZpwrI   r   r   Zcode0r1   r   r2   _print_Piecewise  s,   





z!JuliaCodePrinter._print_Piecewisec           
         s   t |tr| |d}d|S d}dd dd |D }fdd|D } fd	d|D }g }d
}t|D ])\}}	|	dksE|	dkrK||	 q9||| 8 }|d|| |	f  ||| 7 }q9|S )z0Accepts a string of code or a list of code linesTr^   z    )z
^function z^if ^elseif ^else$z^for )z^end$r   r   c                 S   s   g | ]}| d qS )z 	)lstrip)rG   liner1   r1   r2   rg     r   z0JuliaCodePrinter.indent_code.<locals>.<listcomp>c                    &   g | ] t t fd dD qS )c                       g | ]}t | qS r1   r   rG   r   r   r1   r2   rg     r   ;JuliaCodePrinter.indent_code.<locals>.<listcomp>.<listcomp>intanyrG   )	inc_regexr   r2   rg         c                    r   )c                    r   r1   r   r   r   r1   r2   rg     r   r   r   r   )	dec_regexr   r2   rg     r   r   r   z%s%s)r{   r   rC   
splitlinesr   r   rW   )
r-   codeZ
code_linesZtabZincreaseZdecreaseZprettylevelnr   r1   )r   r   r2   rC     s.   




zJuliaCodePrinter.indent_code)2__name__
__module____qualname____doc__ZprintmethodlanguageZ
_operatorsZ_default_settingsr&   r5   r8   r<   r@   rE   rO   r\   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   Z_print_Tupler   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rC   __classcell__r1   r1   r/   r2   r   .   st    J%r   Nc                 K   s   t || |S )a   Converts `expr` to a string of Julia code.

    Parameters
    ==========

    expr : Expr
        A sympy expression to be converted.
    assign_to : optional
        When given, the argument is used as the name of the variable to which
        the expression is assigned.  Can be a string, ``Symbol``,
        ``MatrixSymbol``, or ``Indexed`` type.  This can be helpful for
        expressions that generate multi-line statements.
    precision : integer, optional
        The precision for numbers such as pi  [default=16].
    user_functions : dict, optional
        A dictionary where keys are ``FunctionClass`` instances and values are
        their string representations.  Alternatively, the dictionary value can
        be a list of tuples i.e. [(argument_test, cfunction_string)].  See
        below for examples.
    human : bool, optional
        If True, the result is a single string that may contain some constant
        declarations for the number symbols.  If False, the same information is
        returned in a tuple of (symbols_to_declare, not_supported_functions,
        code_text).  [default=True].
    contract: bool, optional
        If True, ``Indexed`` instances are assumed to obey tensor contraction
        rules and the corresponding nested loops over indices are generated.
        Setting contract=False will not generate loops, instead the user is
        responsible to provide values for the indices in the code.
        [default=True].
    inline: bool, optional
        If True, we try to create single-statement code instead of multiple
        statements.  [default=True].

    Examples
    ========

    >>> from sympy import julia_code, symbols, sin, pi
    >>> x = symbols('x')
    >>> julia_code(sin(x).series(x).removeO())
    'x.^5/120 - x.^3/6 + x'

    >>> from sympy import Rational, ceiling
    >>> x, y, tau = symbols("x, y, tau")
    >>> julia_code((2*tau)**Rational(7, 2))
    '8*sqrt(2)*tau.^(7/2)'

    Note that element-wise (Hadamard) operations are used by default between
    symbols.  This is because its possible in Julia to write "vectorized"
    code.  It is harmless if the values are scalars.

    >>> julia_code(sin(pi*x*y), assign_to="s")
    's = sin(pi*x.*y)'

    If you need a matrix product "*" or matrix power "^", you can specify the
    symbol as a ``MatrixSymbol``.

    >>> from sympy import Symbol, MatrixSymbol
    >>> n = Symbol('n', integer=True, positive=True)
    >>> A = MatrixSymbol('A', n, n)
    >>> julia_code(3*pi*A**3)
    '(3*pi)*A^3'

    This class uses several rules to decide which symbol to use a product.
    Pure numbers use "*", Symbols use ".*" and MatrixSymbols use "*".
    A HadamardProduct can be used to specify componentwise multiplication ".*"
    of two MatrixSymbols.  There is currently there is no easy way to specify
    scalar symbols, so sometimes the code might have some minor cosmetic
    issues.  For example, suppose x and y are scalars and A is a Matrix, then
    while a human programmer might write "(x^2*y)*A^3", we generate:

    >>> julia_code(x**2*y*A**3)
    '(x.^2.*y)*A^3'

    Matrices are supported using Julia inline notation.  When using
    ``assign_to`` with matrices, the name can be specified either as a string
    or as a ``MatrixSymbol``.  The dimensions must align in the latter case.

    >>> from sympy import Matrix, MatrixSymbol
    >>> mat = Matrix([[x**2, sin(x), ceiling(x)]])
    >>> julia_code(mat, assign_to='A')
    'A = [x.^2 sin(x) ceil(x)]'

    ``Piecewise`` expressions are implemented with logical masking by default.
    Alternatively, you can pass "inline=False" to use if-else conditionals.
    Note that if the ``Piecewise`` lacks a default term, represented by
    ``(expr, True)`` then an error will be thrown.  This is to prevent
    generating an expression that may not evaluate to anything.

    >>> from sympy import Piecewise
    >>> pw = Piecewise((x + 1, x > 0), (x, True))
    >>> julia_code(pw, assign_to=tau)
    'tau = ((x > 0) ? (x + 1) : (x))'

    Note that any expression that can be generated normally can also exist
    inside a Matrix:

    >>> mat = Matrix([[x**2, pw, sin(x)]])
    >>> julia_code(mat, assign_to='A')
    'A = [x.^2 ((x > 0) ? (x + 1) : (x)) sin(x)]'

    Custom printing can be defined for certain types by passing a dictionary of
    "type" : "function" to the ``user_functions`` kwarg.  Alternatively, the
    dictionary value can be a list of tuples i.e., [(argument_test,
    cfunction_string)].  This can be used to call a custom Julia function.

    >>> from sympy import Function
    >>> f = Function('f')
    >>> g = Function('g')
    >>> custom_functions = {
    ...   "f": "existing_julia_fcn",
    ...   "g": [(lambda x: x.is_Matrix, "my_mat_fcn"),
    ...         (lambda x: not x.is_Matrix, "my_fcn")]
    ... }
    >>> mat = Matrix([[1, x]])
    >>> julia_code(f(x) + g(x) + g(mat), user_functions=custom_functions)
    'existing_julia_fcn(x) + my_fcn(x) + my_mat_fcn([1 x])'

    Support for loops is provided through ``Indexed`` types. With
    ``contract=True`` these expressions will be turned into loops, whereas
    ``contract=False`` will just print the assignment expression that should be
    looped over:

    >>> from sympy import Eq, IndexedBase, Idx
    >>> len_y = 5
    >>> y = IndexedBase('y', shape=(len_y,))
    >>> t = IndexedBase('t', shape=(len_y,))
    >>> Dy = IndexedBase('Dy', shape=(len_y-1,))
    >>> i = Idx('i', len_y-1)
    >>> e = Eq(Dy[i], (y[i+1]-y[i])/(t[i+1]-t[i]))
    >>> julia_code(e.rhs, assign_to=e.lhs, contract=False)
    'Dy[i] = (y[i + 1] - y[i])./(t[i + 1] - t[i])'
    )r   Zdoprint)r   Z	assign_tor.   r1   r1   r2   
julia_code  s    r  c                 K   s   t t| fi | dS )z~Prints the Julia representation of the given expression.

    See `julia_code` for the meaning of the optional arguments.
    N)printr  )r   r.   r1   r1   r2   print_julia_codeu  s   r  rB   )r   typingr   r   Z
sympy.corer   r   r   r   Zsympy.core.mulr   Zsympy.printing.codeprinterr	   Zsympy.printing.precedencer
   r   r   r   r)   r+   r   r  r  r1   r1   r1   r2   <module>   s.       
A 
