
    EdAS                     <   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 i dddddd	d
ddd ddfd ddfd ddfd ddfd ddfd ddfd ddfgdd ddfgd d!d"d#d$d%d&d&d'd'd(d(d)d)d*d*d+d+d,d,d-d-d.d/d0d1d2dd3Zg d4Z G d5 d6e          Zd:d8Zd9 Zd7S );a  
Rust code printer

The `RustCodePrinter` converts SymPy expressions into Rust expressions.

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

    )AnyDict)SRationalFloatLambda)CodePrinterfloorceilingceilAbsabssignsignumPowc                 $    |t           j         k    S Nr   Onebaseexps     3lib/python3.11/site-packages/sympy/printing/rust.py<lambda>r   G   s    squf}     recip   c                 "    |t           j        k    S r   r   Halfr   s     r   r   r   H   s    saf} r   sqrtc                 $    |t           j         k    S r   r   r   s     r   r   r   I   s    sqvg~ r   zsqrt().recipc                 *    |t          dd          k    S )N      )r   r   s     r   r   r   J   s    shq!nn4 r   cbrtc                 (    | t           j        dz  k    S )Nr   r   r   s     r   r   r   K   s    tquQw r   exp2r%   c                     |j         S r   
is_integerr   s     r   r   r   L   s    s~ r   powir$   c                     |j          S r   r*   r   s     r   r   r   M   s    3>1 r   powfr   c                     dS )NT )r   s    r   r   r   N   s     r   loglnMaxmaxMinminsincostanasinacosatanatan2sinhcoshtanhasinhacoshatanh)r?   r@   rA   rB   rC   r!   )4abstractalignofasbecomeboxbreakconstcontinuecratedoelseenumexternfalsefinalfnforifimplinletloopmacromatchmodmovemutoffsetofoverrideprivprocpubpurerefreturnSelfselfsizeofstaticstructsupertraittruetypetypeofunsafeunsizedusevirtualwherewhileyieldc                   :    e Zd ZdZdZdZdddi dd e            dd	dd

Zi fdZd Z	d Z
d Zd Zd Zd Zd Zd Zd Zd Zd- fd	Zd- fd	Zd Zd Zd Zd Z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% Z"d& Z#d' Z$d( Z%d) Z& fd*Z'd+ Z(d, Z) xZ*S ).RustCodePrinterz>A printer to convert SymPy expressions to strings of Rust code
_rust_codeRustNauto   TF_)
order	full_prec	precisionuser_functionshumancontractdereferenceerror_on_reservedreserved_word_suffixinlinec                 D   t          j        | |           t          t                    | _        |                    di           }| j                            |           t          |                    dg                     | _        t          t                    | _        d S )Nr   r   )	r	   __init__dictknown_functionsgetupdateset_dereferencereserved_words)rh   settings	userfuncss      r   r   zRustCodePrinter.__init__   s    T8,,,#O44LL!1266	##I...]B ? ?@@!.11r   c                     |dz  S )N   r0   )rh   ps     r   _rate_index_positionz$RustCodePrinter._rate_index_position   s    s
r   c                     d|z  S )Nz%s;r0   )rh   
codestrings     r   _get_statementzRustCodePrinter._get_statement   s    z!!r   c                     d|z  S )Nz// %sr0   )rh   texts     r   _get_commentzRustCodePrinter._get_comment   s    ~r   c                     d|d|dS )Nzconst z: f64 = ;r0   )rh   namevalues      r   _declare_number_constz%RustCodePrinter._declare_number_const   s     (,eee44r   c                 ,    |                      |          S r   )indent_code)rh   liness     r   _format_codezRustCodePrinter._format_code   s    &&&r   c                 N    |j         \  }fdt          |          D             S )Nc              3   D   K   | ]}t                    D ]}||fV  	d S r   )range).0ijcolss      r   	<genexpr>z;RustCodePrinter._traverse_matrix_indices.<locals>.<genexpr>  s:      AA1U4[[AAAAAAAAAAr   )shaper   )rh   matrowsr   s      @r   _traverse_matrix_indicesz(RustCodePrinter._traverse_matrix_indices  s.    Y
dAAAAdAAAAr   c           
         g }g }d}|D ]y}|                     ||                     |          |                     |j                  |                     |j        dz             dz             |                     d           z||fS )Nz#for %(var)s in %(start)s..%(end)s {r$   )varstartend})append_printlowerupper)rh   indices
open_linesclose_lines	loopstartr   s         r   _get_loop_opening_endingz(RustCodePrinter._get_loop_opening_ending  s    
9	 	$ 	$Ai{{1~~QW--{{17Q;//+1 +1 1 2 2 2 s####;&&r   c                     t          |j                  dk    rd|                     |          z   dz   S |j        r|                     |d          S |                     |          S )Nr$   ()T)_type)lenargsr   	is_numberrh   exprs     r   _print_caller_varz!RustCodePrinter._print_caller_var  sg    ty>>A 	% T***S00^ 	%;;t4;000;;t$$$r   c                 d    |j         j         j        v r2 j        |j         j                 }d}d}t          |t                    r|}n|D ]\  }}} ||j         r n||dk    rcd                     |j        d                   |t          |j                  dk    r#                     |j        dd         d          nddz  }n{|dk    r'd	                     |j        d                   |d
z  }nN|dk    r'd	                     |j        d                   |d
z  }n!d|                     |j        d          dz  }|S dS t          |d          r<t          |j
        t                    r"                      |j
        |j                   S |j         j         j        v rv j        |j         j                 \  }}                     |          rCt           fd|D                       r*                     |                    |                    S dS dS                      |          S )a<  
        basic function for printing `Function`

        Function Style :

        1. args[0].func(args[1:]), method with arguments
        2. args[0].func(), method without arguments
        3. args[1].func(), method without arguments (e.g. (e, x) => x.exp())
        4. func(args), function with arguments
        Nr$   z%(var)s.%(method)s(%(args)s)r   ,  )r   methodr   r   z%(var)s.%(method)s())r   r   r%   z%(func)s(%(args)s))funcr   _imp_c              3   B   K   | ]}                     |          V  d S r   )
_can_print)r   frh   s     r   r   z2RustCodePrinter._print_Function.<locals>.<genexpr>Q  s/      0Y0Y1C1C0Y0Y0Y0Y0Y0Yr   )r   __name__r   
isinstancestrr   r   r   	stringifyhasattrr   r   r   _rewriteable_functionsr   allrewrite_print_not_supported)	rh   r   	cond_funcr   stylecondrettarget_frequired_fss	   `        r   _print_FunctionzRustCodePrinter._print_Function  s    9!55 *	3,TY-?@IDE)S))  )2  %D$tTY'  A: 8#55dilCC"&GJ49~~XYGY aty}d C C C_a< < CC
 aZ 0#55dilCC"&4 4 CC aZ 	0#55dilCC"&4 4 CC
 / $ $ty$ ? ?2 2 C 
- . T7## 		3
4:v(F(F 		3;;ztz495666Y4#>> 	3$($?	@R$S!Hkx(( ;S0Y0Y0Y0Y[0Y0Y0Y-Y-Y ;{{4<<#9#9:::; ; ; ; ,,T222r   c                     |j         j        rQ|j        j        sE t          |          t	          |j                   |j                  }|                     |          S |                     |          S r   )r   r+   r   ro   r   r   r   r   s     r   
_print_PowzRustCodePrinter._print_PowV  sd    9 	%(; 	%4::eDI..99D;;t$$$##D)))r   c                 X    t                                          |          }|r|dz   S |S )N_f64)rl   _print_Floatrh   r   r   r   	__class__s       r   r   zRustCodePrinter._print_Float\  s1    gg""4(( 	<Jr   c                 X    t                                          |          }|r|dz   S |S )N_i32)rl   _print_Integerr   s       r   r   zRustCodePrinter._print_Integerc  s1    gg$$T** 	<Jr   c                 `    t          |j                  t          |j                  }}d||fz  S )Nz%d_f64/%d.0)intr   q)rh   r   r   r   s       r   _print_RationalzRustCodePrinter._print_Rationalj  s*    46{{CKK11v%%r   c                     |                      |j                  }|                      |j                  }|j        }d                    |||          S )Nz{} {} {})r   lhsrhsrel_opformat)rh   r   lhs_coderhs_codeops        r   _print_Relationalz!RustCodePrinter._print_Relationaln  sG    ;;tx((;;tx(([  2x888r   c                 4   |j         }t          j        }t          j        }t	          t          |j                            D ] }||j        |         |z  z  }|||         z  }!|                     |j	        j
                  d|                     |          dS )N[])r   r   Zeror   reversedr   rankr   r   r   label)rh   r   dimselemoffsetr   s         r   _print_IndexedzRustCodePrinter._print_Indexedt  s    zv%	**++ 	 	ADLOF**Dd1gFF;;ty7777T9J9J9J9JKKr   c                     |j         j        S r   )r  r   r   s     r   
_print_IdxzRustCodePrinter._print_Idx~  s    zr   c                     |j         S r   )r   r   s     r   _print_DummyzRustCodePrinter._print_Dummy  s
    yr   c                     dS )NEr0   rh   r   r   s      r   _print_Exp1zRustCodePrinter._print_Exp1  s    sr   c                     dS )NPIr0   r  s      r   	_print_PizRustCodePrinter._print_Pi  s    tr   c                     dS )NINFINITYr0   r  s      r   _print_InfinityzRustCodePrinter._print_Infinity  s    zr   c                     dS )NNEG_INFINITYr0   r  s      r   _print_NegativeInfinityz'RustCodePrinter._print_NegativeInfinity  s    ~r   c                     dS )Nrn   r0   r  s      r   _print_BooleanTruez"RustCodePrinter._print_BooleanTrue  s    vr   c                     dS )NrQ   r0   r  s      r   _print_BooleanFalsez#RustCodePrinter._print_BooleanFalse  s    wr   c                 D    t          |                                          S r   )r   r   r  s      r   _print_boolzRustCodePrinter._print_bool  s    4yy   r   c                     dS )NNANr0   r  s      r   
_print_NaNzRustCodePrinter._print_NaN  s    ur   c                    |j         d         j        dk    rt          d          g }t          |j                   D ]\  }\  }}|dk    r,|                    d|                     |          z             nX|t          |j                   dz
  k    r|dk    r|dxx         dz  cc<   n&|dxx         d|                     |          z  z  cc<   |                     |          }|                    |           |                    d	           | j        d
         rd                    |          S d                    |          S )NTzAll 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   z	if (%s) {r$   z else {z else if (%s) {r   r    
)	r   r   
ValueError	enumerater   r   r   	_settingsjoin)rh   r   r   r   eccode0s          r   _print_Piecewisez RustCodePrinter._print_Piecewise  sV   9R=% 	0  / 0 0 0
 "49-- 		 		IAv1Av @[4;;q>>9::::c$)nnq(( @Q$Y @b			Y&				b			.Q??			KKNNELLLL>(# 	$88E??"99U###r   c                 b    ddl m} |                     |                    |d                    S )Nr   )	PiecewiseF)deep)sympy.functionsr-  r   r   )rh   r   r-  s      r   
_print_ITEzRustCodePrinter._print_ITE  s6    ------{{4<<	<>>???r   c                      |j         dk    r$dd                     fd|D                       z  S t          d          )Nr$   z[%s]r   c              3   B   K   | ]}                     |          V  d S r   )r   )r   arh   s     r   r   z4RustCodePrinter._print_MatrixBase.<locals>.<genexpr>  s-      %@%@dkk!nn%@%@%@%@%@%@r   zLFull Matrix Support in Rust need Crates (https://crates.io/keywords/matrix).)r   r'  r$  )rh   As   ` r   _print_MatrixBasez!RustCodePrinter._print_MatrixBase  sM    6Q; 	mDII%@%@%@%@a%@%@%@@@@@klllr   c                 ,    |                      |          S r   )r   )rh   r   s     r   _print_SparseRepMatrixz&RustCodePrinter._print_SparseRepMatrix  s    ((---r   c                 \    |j         d|j        |j        |j         j        d         z  z   dS )Nr   r$   r   )parentr   r   r   r   s     r   _print_MatrixElementz$RustCodePrinter._print_MatrixElement  s8    ;;;6DF4;+<Q+?$????A 	Ar   c                 f    t                                          |          }|| j        v rd|z  S |S )Nz(*%s))rl   _print_Symbolr   )rh   r   r   r   s      r   r<  zRustCodePrinter._print_Symbol  s9    ww$$T**4$$ 	T>!Kr   c                 L   ddl m} |j        }|j        }| j        d         r@|                    |          s|                    |          r|                     ||          S |                     |          }|                     |          }|                     |d|          S )Nr   )IndexedBaser   z = )	sympy.tensor.indexedr>  r   r   r&  has_doprint_loopsr   r   )rh   r   r>  r   r   r   r   s          r   _print_Assignmentz!RustCodePrinter._print_Assignment  s    444444hh>*% 	I377;+?+? 	I$$	I &&sC000{{3''H{{3''H&&HHHhh'GHHHr   c                   
 t          |t                    r=|                     |                    d                    }d                    |          S d}dd
d |D             }fd|D             }
fd|D             }g }d	}t          |          D ]Q\  }}	|	d
v r|                    |	           |||         z  }|                    ||z  |	           |||         z  }R|S )z0Accepts a string of code or a list of code linesTr   z    ){r   z{
z(
)r   r   c                 8    g | ]}|                     d           S )z 	)lstrip)r   lines     r   
<listcomp>z/RustCodePrinter.indent_code.<locals>.<listcomp>  s$    666U##666r   c           
      n    g | ]1}t          t          t          |j                                      2S r0   )r   anymapendswith)r   rG  	inc_tokens     r   rH  z/RustCodePrinter.indent_code.<locals>.<listcomp>  s5    OOOSS	::;;<<OOOr   c           
      n    g | ]1}t          t          t          |j                                      2S r0   )r   rJ  rK  
startswith)r   rG  	dec_tokens     r   rH  z/RustCodePrinter.indent_code.<locals>.<listcomp>  sE     ( ( ( S)<<==>> ( ( (r   r   )r   r#  )r   r   r   
splitlinesr'  r%  r   )rh   code
code_linestabincreasedecreaseprettylevelnrG  rP  rM  s             @@r   r   zRustCodePrinter.indent_code  s5    dC   	'))$//$*?*?@@J77:&&&,		66666OOOOOOO( ( ( (!%( ( (   	! 	!GAtz! d###Xa[ EMMCIItt4555Xa[ EEr   )F)+r   
__module____qualname____doc__printmethodlanguager   _default_settingsr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r	  r  r  r  r  r  r  r  r  r+  r0  r5  r7  r:  r<  rB  r   __classcell__)r   s   @r   ry   ry      s       HHKH suu" #  !# 2 2 2 2  " " "  5 5 5' ' 'B B B' ' '	% 	% 	%63 63 63p* * *          & & &9 9 9L L L                      ! ! ! !   $ $ $6@ @ @m m m. . .A A A    I I I      r   ry   Nc                 H    t          |                              | |          S )a  Converts an expr to a string of Rust 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 is helpful in case of
        line-wrapping, or for expressions that generate multi-line statements.
    precision : integer, optional
        The precision for numbers such as pi [default=15].
    user_functions : dict, optional
        A dictionary where the keys are string representations of either
        ``FunctionClass`` or ``UndefinedFunction`` instances and the values
        are their desired C string representations. Alternatively, the
        dictionary value can be a list of tuples i.e. [(argument_test,
        cfunction_string)].  See below for examples.
    dereference : iterable, optional
        An iterable of symbols that should be dereferenced in the printed code
        expression. These would be values passed by address to the function.
        For example, if ``dereference=[a]``, the resulting code would print
        ``(*a)`` instead of ``a``.
    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].

    Examples
    ========

    >>> from sympy import rust_code, symbols, Rational, sin, ceiling, Abs, Function
    >>> x, tau = symbols("x, tau")
    >>> rust_code((2*tau)**Rational(7, 2))
    '8*1.4142135623731*tau.powf(7_f64/2.0)'
    >>> rust_code(sin(x), assign_to="s")
    's = x.sin();'

    Simple 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)].

    >>> custom_functions = {
    ...   "ceiling": "CEIL",
    ...   "Abs": [(lambda x: not x.is_integer, "fabs", 4),
    ...           (lambda x: x.is_integer, "ABS", 4)],
    ...   "func": "f"
    ... }
    >>> func = Function('func')
    >>> rust_code(func(Abs(x) + ceiling(x)), user_functions=custom_functions)
    '(fabs(x) + x.CEIL()).f()'

    ``Piecewise`` expressions are converted into conditionals. If an
    ``assign_to`` variable is provided an if statement is created, otherwise
    the ternary operator is used. 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
    >>> expr = Piecewise((x + 1, x > 0), (x, True))
    >>> print(rust_code(expr, tau))
    tau = if (x > 0) {
        x + 1
    } else {
        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]))
    >>> rust_code(e.rhs, assign_to=e.lhs, contract=False)
    'Dy[i] = (y[i + 1] - y[i])/(t[i + 1] - t[i]);'

    Matrices are also supported, but a ``MatrixSymbol`` of the same dimensions
    must be provided to ``assign_to``. Note that any expression that can be
    generated normally can also exist inside a Matrix:

    >>> from sympy import Matrix, MatrixSymbol
    >>> mat = Matrix([x**2, Piecewise((x + 1, x > 0), (x, True)), sin(x)])
    >>> A = MatrixSymbol('A', 3, 1)
    >>> print(rust_code(mat, A))
    A = [x.powi(2), if (x > 0) {
        x + 1
    } else {
        x
    }, x.sin()];
    )ry   doprint)r   	assign_tor   s      r   	rust_coderd    s#    Z 8$$,,T9===r   c                 :    t          t          | fi |           dS )z3Prints Rust representation of the given expression.N)printrd  )r   r   s     r   print_rust_coderg  m  s&    	)D
%
%H
%
%&&&&&r   r   )r\  typingr   r   tDict
sympy.corer   r   r   r   sympy.printing.codeprinterr	   r   r   ry   rd  rg  r0   r   r   <module>rl     sL  	 	B & % % % % % % % 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2$2 W2 v2 
52 H2  
,,gq9,,fa8--~qA44fa@..:--vq91161=?!2. 
ua()/20 
412< 
5=2> 
5?2B 
5C2D 
5E2F 
5G2H FI2J FK2L FM2N WO2V FW2X c2 2 2X3 3 3la a a a ak a a aH	m> m> m> m>`' ' ' ' 'r   