B
    }[X              2   @   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
mZ ddlmZ ddlmZmZ ddlmZmZ ddlmZ d	d
dddddddddddddddddddddd d!d"d#d$d%d&d'd(d)d*d+d,d-d.d/d0d1d2d3d4d5d6d7d8d9d:g2Zd;d<d=d>d?d@dAdBZG dCdD dDeZdJdFdGZdHdI ZdES )Ka  
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.

    )print_functiondivision)MulPowSRational)string_typesrange)_keep_coeff)CodePrinter
Assignment)
precedence
PRECEDENCE)searchZsinZcosZtanZcotZsecZcscZasinZacosZatanZacotZasecZacscZsinhZcoshZtanhZcothZsechZcschZasinhZacoshZatanhZacothZasechZ	acschsincZ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 fd$d%Zd&d' Z fd(d)Z fd*d+Z fd,d-Z fd.d/Zd0d1 Zd2d3 Zd4d5 Zd6d7 Zd8d9 Zd:d; ZeZd<d= Z d>d? Z!d@dA Z"dBdC Z#dDdE Z$e# Z% Z& Z' Z(Z)e$ Z*Z+dFdG Z,dHdI Z-dJdK Z.dLdM Z/dNdO Z0dPdQ Z1dRdS Z2dTdU Z3dVdW Z4  Z5S )X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                sL   t t| | tttt| _| jtt |	di }| j| d S )Nr$   )
superr   __init__dictzipknown_fcns_src1Zknown_functionsupdateknown_fcns_src2get)selfsettingsZ	userfuncs)	__class__ 3lib/python3.7/site-packages/sympy/printing/julia.pyr(   I   s
    zJuliaCodePrinter.__init__c             C   s   |d S )N   r2   )r/   pr2   r2   r3   _rate_index_positionQ   s    z%JuliaCodePrinter._rate_index_positionc             C   s   d| S )Nz%sr2   )r/   Z
codestringr2   r2   r3   _get_statementU   s    zJuliaCodePrinter._get_statementc             C   s
   d |S )Nz# {0})format)r/   textr2   r2   r3   _get_commentY   s    zJuliaCodePrinter._get_commentc             C   s   d ||S )Nzconst {0} = {1})r8   )r/   namevaluer2   r2   r3   _declare_number_const]   s    z&JuliaCodePrinter._declare_number_constc             C   s
   |  |S )N)indent_code)r/   linesr2   r2   r3   _format_codea   s    zJuliaCodePrinter._format_codec                s    |j \ } fddt|D S )Nc             3   s$   | ]}t  D ]}||fV  qqd S )N)r	   ).0ji)rowsr2   r3   	<genexpr>h   s    z<JuliaCodePrinter._traverse_matrix_indices.<locals>.<genexpr>)shaper	   )r/   Zmatcolsr2   )rD   r3   _traverse_matrix_indicese   s    
z)JuliaCodePrinter._traverse_matrix_indicesc             C   sb   g }g }xP|D ]H}t | j|j|jd |jd g\}}}|d|||f  |d qW ||fS )N   zfor %s = %s:%send)map_printlabellowerupperappend)r/   indicesZ
open_linesZclose_linesrC   varstartstopr2   r2   r3   _get_loop_opening_endingk   s    
 z)JuliaCodePrinter._get_loop_opening_endingc                s  |j r0|jr0| d jr0dtj |  S t| | \}}|dk r^t| |}d}nd}g }g }g }j	dkr|
 }n
t|}x|D ]}	|	jr&|	jr&|	jjr&|	jjr&|	jdkr|t|	j|	j dd nDt|	jd jd	krt|	jtr||	 |t|	j|	j  q|	jrt|	tjk	rt|	jd	krV|t|	j |	jd	kr~|t|	j q||	 qW |ptjg} fd
d|D }
 fdd|D }x:|D ]2}	|	j|krd|||	j  |||	j< qW dd }t|dkr||||
 S t|d	krT|d j r6dnd}||||
 | |d  S tdd |D rldnd}||||
 | d|||  S d S )Nr   z%sim- )oldZnoneF)ZevaluaterI   c                s   g | ]} | qS r2   )parenthesize)rA   x)precr/   r2   r3   
<listcomp>   s    z/JuliaCodePrinter._print_Mul.<locals>.<listcomp>c                s   g | ]} | qS r2   )rZ   )rA   r[   )r\   r/   r2   r3   r]      s    z(%s)c             S   sJ   |d }x<t dt| D ]*}| |d  jr.dnd}|| ||  }qW |S )Nr   rI   *z.*)r	   len	is_number)aa_strrrC   Zmulsymr2   r2   r3   multjoin   s
    z-JuliaCodePrinter._print_Mul.<locals>.multjoin/z./c             S   s   g | ]
}|j qS r2   )r`   )rA   Zbir2   r2   r3   r]      s    )r`   Zis_imaginaryZas_coeff_Mul
is_integerrL   r   ZImaginaryUnitr   r
   r#   Zas_ordered_factorsr   Z	make_argsis_commutativeZis_Powr   Zis_RationalZis_negativerP   r   baser_   args
isinstanceZInfinityr5   r   qOneindexall)r/   exprcer   ra   bZ	pow_parenri   itemrb   Zb_strrd   Zdivsymr2   )r\   r/   r3   
_print_Mulw   sV    





$

&zJuliaCodePrinter._print_Mulc             C   s   t dd |jD rdnd}t|}|jtjkr@d| |j S |jr|jtj kr||jj	r`dnd}d| d| |j  S |jtj
 kr|jj	rdnd}d| d	| |j|  S d
| |j||| |j|f S )Nc             S   s   g | ]
}|j qS r2   )r`   )rA   r[   r2   r2   r3   r]      s    z/JuliaCodePrinter._print_Pow.<locals>.<listcomp>^z.^zsqrt(%s)re   z./1z%sz%s%s%s)rn   ri   r   r   r   HalfrL   rh   rg   r`   rl   rZ   )r/   ro   Z	powsymbolPRECZsymr2   r2   r3   
_print_Pow   s    zJuliaCodePrinter._print_Powc             C   s(   t |}d| |j|| |j|f S )Nz%s^%s)r   rZ   rh   r   )r/   ro   rx   r2   r2   r3   _print_MatPow   s    zJuliaCodePrinter._print_MatPowc                s"   | j d rdS tt| |S d S )Nr&   Zpi)	_settingsr'   r   _print_NumberSymbol)r/   ro   )r1   r2   r3   	_print_Pi   s    
zJuliaCodePrinter._print_Pic             C   s   dS )Nr   r2   )r/   ro   r2   r2   r3   _print_ImaginaryUnit   s    z%JuliaCodePrinter._print_ImaginaryUnitc                s"   | j d rdS tt| |S d S )Nr&   rq   )r{   r'   r   r|   )r/   ro   )r1   r2   r3   _print_Exp1   s    
zJuliaCodePrinter._print_Exp1c                s"   | j d rdS tt| |S d S )Nr&   Z
eulergamma)r{   r'   r   r|   )r/   ro   )r1   r2   r3   _print_EulerGamma   s    
z"JuliaCodePrinter._print_EulerGammac                s"   | j d rdS tt| |S d S )Nr&   Zcatalan)r{   r'   r   r|   )r/   ro   )r1   r2   r3   _print_Catalan   s    
zJuliaCodePrinter._print_Catalanc                s"   | j d rdS tt| |S d S )Nr&   Zgolden)r{   r'   r   r|   )r/   ro   )r1   r2   r3   _print_GoldenRatio   s    
z#JuliaCodePrinter._print_GoldenRatioc             C   s   ddl m} ddlm} |j}|j}| jd st|j|rg }g }x,|jD ]"\}}	|	t
|| |	|	 qJW |t|| }
| |
S | jd r||s||r| ||S | |}| |}| d||f S d S )Nr   )	Piecewise)IndexedBaser&   r%   z%s = %s)Z$sympy.functions.elementary.piecewiser   Zsympy.tensor.indexedr   lhsrhsr{   rj   ri   rP   r   r*   rL   ZhasZ_doprint_loopsr7   )r/   ro   r   r   r   r   ZexpressionsZ
conditionsrq   rp   ZtempZlhs_codeZrhs_coder2   r2   r3   _print_Assignment  s$    



z"JuliaCodePrinter._print_Assignmentc             C   s   dS )NZInfr2   )r/   ro   r2   r2   r3   _print_Infinity  s    z JuliaCodePrinter._print_Infinityc             C   s   dS )Nz-Infr2   )r/   ro   r2   r2   r3   _print_NegativeInfinity#  s    z(JuliaCodePrinter._print_NegativeInfinityc             C   s   dS )NZNaNr2   )r/   ro   r2   r2   r3   
_print_NaN'  s    zJuliaCodePrinter._print_NaNc                s    dd  fdd|D  d S )NzAny[z, c             3   s   | ]}  |V  qd S )N)rL   )rA   ra   )r/   r2   r3   rE   ,  s    z/JuliaCodePrinter._print_list.<locals>.<genexpr>])join)r/   ro   r2   )r/   r3   _print_list+  s    zJuliaCodePrinter._print_listc             C   s2   t |dkrd| |d  S d| |d S d S )NrI   z(%s,)r   z(%s)z, )r_   rL   Z	stringify)r/   ro   r2   r2   r3   _print_tuple/  s    zJuliaCodePrinter._print_tuplec             C   s   dS )Ntruer2   )r/   ro   r2   r2   r3   _print_BooleanTrue7  s    z#JuliaCodePrinter._print_BooleanTruec             C   s   dS )NZfalser2   )r/   ro   r2   r2   r3   _print_BooleanFalse;  s    z$JuliaCodePrinter._print_BooleanFalsec             C   s   t | S )N)strrN   )r/   ro   r2   r2   r3   _print_bool?  s    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r`d|j dddd	 S |jdkrdd
 fdd|D  S d|j ddddd S )Nr   zzeros(%s, %s))rI   rI   z[%s])r   r   rI   rW    )rowstartrowendcolsepz, c                s   g | ]}  |qS r2   )rL   )rA   ra   )r/   r2   r3   r]   Q  s    z6JuliaCodePrinter._print_MatrixBase.<locals>.<listcomp>z;
)r   r   Zrowsepr   )rD   rG   tabler   )r/   Ar2   )r/   r3   _print_MatrixBaseG  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   rI   r2   )rA   kr2   r2   r3   r]   Z  s    z8JuliaCodePrinter._print_SparseMatrix.<locals>.<listcomp>c             S   s   g | ]}|d  d  qS )rI   r2   )rA   r   r2   r2   r3   r]   [  s    c             S   s   g | ]}|d  qS )   r2   )rA   r   r2   r2   r3   r]   \  s    zsparse(%s, %s, %s, %s, %s))Zsympy.matricesr   Zcol_listrL   rD   rG   )r/   r   r   LIJZAIJr2   r2   r3   _print_SparseMatrixV  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]rI   )rZ   parentr   rC   rB   )r/   ro   r2   r2   r3   _print_MatrixElemento  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r2dn  |}|dkrr|dkrX||krXdS ||krd|S |d | S nd|  ||fS d S )Nr   rI   r   rJ   :)rL   r   )r[   ZlimlhstepZlstrZhstr)r/   r2   r3   strsliceu  s    
z5JuliaCodePrinter._print_MatrixSlice.<locals>.strslice[r   ,rI   r   )rL   r   ZrowslicerF   Zcolslice)r/   ro   r   r2   )r/   r3   _print_MatrixSlicet  s    z#JuliaCodePrinter._print_MatrixSlicec                s0    fdd|j D }d |jjd|f S )Nc                s   g | ]}  |qS r2   )rL   )rA   rC   )r/   r2   r3   r]     s    z3JuliaCodePrinter._print_Indexed.<locals>.<listcomp>z%s[%s]r   )rQ   rL   rh   rM   r   )r/   ro   Zindsr2   )r/   r3   _print_Indexed  s    zJuliaCodePrinter._print_Indexedc             C   s   |  |jS )N)rL   rM   )r/   ro   r2   r2   r3   
_print_Idx  s    zJuliaCodePrinter._print_Idxc             C   s   d|  |jd  S )Nzeye(%s)r   )rL   rF   )r/   ro   r2   r2   r3   _print_Identity  s    z JuliaCodePrinter._print_Identityc             C   sD   ddl m}m} |j}|tjd|  ||jtj | }| |S )Nr   )r   r   r   )	sympy.functionsr   r   argumentr   Pir#   rw   rL   )r/   ro   r   r   r[   expr2r2   r2   r3   	_print_jn  s    $zJuliaCodePrinter._print_jnc             C   sD   ddl m}m} |j}|tjd|  ||jtj | }| |S )Nr   )r   r   r   )	r   r   r   r   r   r   r#   rw   rL   )r/   ro   r   r   r[   r   r2   r2   r3   	_print_yn  s    $zJuliaCodePrinter._print_ync       
         s$  |j d jdkrtdg } jd rr fdd|j d d D }d |j d j }d|| }d	| d
 S xt|j D ]\}\}}|dkr|d |  n:|t	|j d kr|dkr|d n|d |   |}	||	 |t	|j d kr~|d q~W d|S d S )NrY   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({0}) ? ({1}) :)r8   rL   )rA   rq   rp   )r/   r2   r3   r]     s   z5JuliaCodePrinter._print_Piecewise.<locals>.<listcomp>z (%s)
()r   zif (%s)rI   elsezelseif (%s)rJ   )
ri   Zcond
ValueErrorr{   rL   ro   r   	enumeraterP   r_   )
r/   ro   r?   ZecpairsZelastZpwrC   rq   rp   Zcode0r2   )r/   r3   _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
}x^t|D ]R\}}	|	dks|	dkr||	 qt||| 8 }|d|| |	f  ||| 7 }qtW |S )z0Accepts a string of code or a list of code linesTrW   z    )z
^function z^if z^elseif z^else$z^for )z^end$z^elseif z^else$c             S   s   g | ]}| d qS )z 	)lstrip)rA   liner2   r2   r3   r]     s    z0JuliaCodePrinter.indent_code.<locals>.<listcomp>c                s&   g | ] t t fd dD qS )c                s   g | ]}t | qS r2   )r   )rA   r   )r   r2   r3   r]     s    z;JuliaCodePrinter.indent_code.<locals>.<listcomp>.<listcomp>)intany)rA   )	inc_regex)r   r3   r]     s   c                s&   g | ] t t fd dD qS )c                s   g | ]}t | qS r2   )r   )rA   r   )r   r2   r3   r]     s    z;JuliaCodePrinter.indent_code.<locals>.<listcomp>.<listcomp>)r   r   )rA   )	dec_regex)r   r3   r]     s   r   r   z%s%s)rj   r   r>   
splitlinesr   r   rP   )
r/   codeZ
code_linesZtabZincreaseZdecreaseZprettylevelnr   r2   )r   r   r3   r>     s*    




zJuliaCodePrinter.indent_code)6__name__
__module____qualname____doc__ZprintmethodZlanguageZ
_operatorsZ_default_settingsr(   r6   r7   r:   r=   r@   rH   rU   rt   ry   rz   r}   r~   r   r   r   r   r   r   r   r   r   r   Z_print_Tupler   r   r   r   r   Z_print_MatrixZ_print_DenseMatrixZ_print_MutableDenseMatrixZ_print_ImmutableMatrixZ_print_ImmutableDenseMatrixZ_print_MutableSparseMatrixZ_print_ImmutableSparseMatrixr   r   r   r   r   r   r   r   r>   __classcell__r2   r2   )r1   r3   r   .   sl   K%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, Abs
    >>> 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, ccode
    >>> 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)ro   Z	assign_tor0   r2   r2   r3   
julia_code  s     r   c             K   s   t t| f| dS )z~Prints the Julia representation of the given expression.

    See `julia_code` for the meaning of the optional arguments.
    N)printr   )ro   r0   r2   r2   r3   print_julia_codes  s    r   )N)r   Z
__future__r   r   Z
sympy.corer   r   r   r   Zsympy.core.compatibilityr   r	   Zsympy.core.mulr
   Zsympy.printing.codeprinterr   r   Zsympy.printing.precedencer   r   r   r   r+   r-   r   r   r   r2   r2   r2   r3   <module>
   s@   

   ?
 
