o
    Th_Q                     @  s  d Z ddlmZ ddlmZ ddl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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 ddlmZ G dd deZG dd deZ eefee fdZ!i ddddddddd ddfdd ddfdd ddfdd d dfd!d d"d#fd$d d%d&fd'd d(d&fgd)d*d d)dfgd+d,d-d.d/d0d1d1d2d2d3d3d4d4d5d5d6d6d7d7d8d8d9d9d:d;d<d=dd>Z"g d?Z#G d@dA dAeZ$G dBdC dCeZ%dS )Da  
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.

    )annotations)reduceN)Any)float32float64int32realintegerbool_)SRationalFloatLambda)Exprequal_valued)ceilingfloor)CodePrinter)
PRECEDENCEc                   @     e Zd ZdZdd ZdS )float_floorzi
    Same as `sympy.floor`, but mimics the Rust behavior of returning a float rather than an integer
    c                 C     dS NF selfr   r   T/home/air/segue/gemini/back/venv/lib/python3.10/site-packages/sympy/printing/rust.py_eval_is_integerE      zfloat_floor._eval_is_integerN__name__
__module____qualname____doc__r   r   r   r   r   r   A       r   c                   @  r   )float_ceilingzk
    Same as `sympy.ceiling`, but mimics the Rust behavior of returning a float rather than an integer
    c                 C  r   r   r   r   r   r   r   r   L   r   zfloat_ceiling._eval_is_integerNr    r   r   r   r   r&   H   r%   r&   )r   r   r   ceilAbsabsPowc                 C  
   t |dS )Nr   baseexpr   r   r   <lambda>f      
 r0   recip   c                 C  r+   )Ng      ?r   r-   r   r   r   r0   g   r1   sqrtc                 C  r+   )Ng      r   r-   r   r   r   r0   h   r1   zsqrt().recipc                 C  s   |t ddkS )N      )r   r-   r   r   r   r0   i   s    cbrtc                 C  s
   t | dS )Nr3   r   r-   r   r   r   r0   j   r1   exp2r6   c                 C     |j S N
is_integerr-   r   r   r   r0   k   s    powir5   c                 C  s   |j  S r:   r;   r-   r   r   r   r0   l   s    powfr/   c                 C  r   )NTr   )r/   r   r   r   r0   m   s    loglnMaxmaxMinminsincostanasinacosatanatan2sinhcoshtanhasinhacoshatanh)rN   rO   rP   rQ   r4   )4abstractasasyncawaitbecomeboxbreakconstcontinuecratedodynelseenumexternfalsefinalfnforgenifimplinletloopmacromatchmodmovemutoverrideprivpubrefreturnSelfr   staticstructsupertraittruetrytypetypeofunsafeunsizedusevirtualwherewhileyieldc                      sD   e Zd ZdZd fddZedd Zedd	 ZdddZ  Z	S )TypeCastz9
    The type casting operator of the Rust language.
    rt   Nonec                   sD   t    |jo|tu| _|j| _| jr t| dtd d  d S d S )N
precedenceFunc
   )rx   __init__r<   r	   explicit_assumptionssetattrr   )r   exprtype_	__class__r   r   r      s   
zTypeCast.__init__c                 C  
   | j d S )Nr   argsr   r   r   r   r        
zTypeCast.exprc                 C  r   )Nr5   r   r   r   r   r   r     r   zTypeCast.type_Nc                 C  s   | j d j|dS )Nr   )order)r   sort_key)r   r   r   r   r   r     s   zTypeCast.sort_key)rt   r   r:   )
r!   r"   r#   r$   r   propertyr   r   r   __classcell__r   r   r   r   r      s    

r   c                      s  e Zd ZU dZdZdZeeee	iZ
edede	dediZeejfi di d	e d
Zded< i 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 fd!d"Zdc fd$d%	Zd&d' Zd(d) Z dd fd+d,	Z!dd fd-d.	Z"d/d0 Z#d1d2 Z$d3d4 Z%d5d6 Z&d7d8 Z'ddd9d:Z(ddd;d<Z)ddd=d>Z*ddd?d@Z+dddAdBZ,dddCdDZ-dddEdFZ.dddGdHZ/dIdJ Z0dKdL Z1dMdN Z2dOdP Z3dQdR Z4 fdSdTZ5dUdV Z6dWdX Z7dYdZ Z8d[d\ Z9d]d^ Z:d_d` Z;dadb Z<  Z=S )eRustCodePrinterz>A printer to convert SymPy expressions to strings of Rust code
_rust_codeRusti32f32f64bool   T)	precisionuser_functionscontractdereferencezdict[str, Any]_default_settingsc                 C  sT   t | | tt| _|di }| j| t|dg | _tt| _t	| _	d S )Nr   r   )
r   r   dictknown_functionsgetupdateset_dereferencereserved_wordsfunction_overrides)r   settings	userfuncsr   r   r   r   (  s   


zRustCodePrinter.__init__c                 C  s   |d S )N   r   )r   pr   r   r   _rate_index_position1     z$RustCodePrinter._rate_index_positionc                 C     d| S )Nz%s;r   )r   
codestringr   r   r   _get_statement4  r   zRustCodePrinter._get_statementc                 C  r   )Nz// %sr   )r   textr   r   r   _get_comment7  r   zRustCodePrinter._get_commentc                 C  s   | j | jt  }d|||f S )Nzconst %s: %s = %s;)type_mappingstype_aliasesr   )r   namevaluer   r   r   r   _declare_number_const:  s   z%RustCodePrinter._declare_number_constc                 C  
   |  |S r:   )indent_code)r   linesr   r   r   _format_code>  s   
zRustCodePrinter._format_codec                   s    |j \}  fddt|D S )Nc                 3  s&    | ]}t  D ]}||fV  qqd S r:   )range).0ijcolsr   r   	<genexpr>C     $ z;RustCodePrinter._traverse_matrix_indices.<locals>.<genexpr>)shaper   )r   matrowsr   r   r   _traverse_matrix_indicesA  s   
z(RustCodePrinter._traverse_matrix_indicesc              
   C  sX   g }g }d}|D ]}| || || |j| |jd d  | d q||fS )Nz#for %(var)s in %(start)s..%(end)s {r5   )varstartend})append_printlowerupper)r   indices
open_linesclose_lines	loopstartr   r   r   r   _get_loop_opening_endingE  s   

z(RustCodePrinter._get_loop_opening_endingc                 C  s>   t |jdkrd| | d S |jr| j|ddS | |S )Nr5   ()T)_type)lenr   r   	is_numberr   r   r   r   r   _print_caller_varR  s
   
z!RustCodePrinter._print_caller_varc                 C  sD  |j j| jv r| j|j j }d}d}t|tr|}n|D ]\}}}||j r( nq|dur|dkrSd| |jd |t|jdkrL| |jdd dndd }|S |dkrfd	| |jd |d
 }|S |dkryd	| |jd |d
 }|S d|| |jdd }|S dS t	|drt|j
tr| |j
|j 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
        Nr5   z%(var)s.%(method)s(%(args)s)r   ,  )r   methodr   r3   z%(var)s.%(method)s())r   r   r6   z%(func)s(%(args)s))funcr   _imp_)r   r!   r   
isinstancestrr   r   r   	stringifyhasattrr   r   r   _print_not_supported)r   r   	cond_funcr   stylecondretr   r   r   _print_Function]  sN   

&	
zRustCodePrinter._print_Functionc                   s@   t dd |jD }|rttj fdd|jD }t |S )Nc                 s      | ]
}|j o
|j V  qd S r:   is_realr<   r   argr   r   r   r         z-RustCodePrinter._print_Mul.<locals>.<genexpr>c                 3  s&    | ]}|d kr  |n|V  qdS )r,   N_cast_to_floatr   r   r   r   r     r   )anyr   r   operatormulrx   
_print_Mul)r   r   contains_floatsr   r   r   r     s   zRustCodePrinter._print_MulNc                   sB   t dd |jD }|rttj fdd|jD }t ||S )Nc                 s  r   r:   r   r   r   r   r   r     r   z-RustCodePrinter._print_Add.<locals>.<genexpr>c                 3      | ]}  |V  qd S r:   r   r   r   r   r   r         )r   r   r   r   addrx   
_print_Add)r   r   r   r   r   r   r   r    s   zRustCodePrinter._print_Addc                 C  s:   |j jr|jjst|t|j |j}| |S | |S r:   )r.   r<   r/   r|   r   r   r   r   r   r   r   
_print_Pow  s   

zRustCodePrinter._print_Powc                 C  s4   |j s	| |jS | |jd| j| j|j    S )Nz as %s)r   r   r   r   r   r   r   r   r   r   _print_TypeCast  s   "zRustCodePrinter._print_TypeCastFc                   ,   t  |}|r|d| j| jt    S |S Nz_%s)rx   _print_Floatr   r   r   r   r   r   r   r   r   r   r       zRustCodePrinter._print_Floatc                   r  r  )rx   _print_Integerr   r   r	   r  r   r   r   r
    r	  zRustCodePrinter._print_Integerc                 C  s4   t |jt |j}}| j| jt  }d|||f S )Nz
%d_%s/%d.0)intr   qr   r   r   )r   r   r   r  float_suffixr   r   r   _print_Rational  s   zRustCodePrinter._print_Rationalc                 C  sn   |j jr|jjr|jjr|j js| |j }| |j}n|j }|j}| |}| |}|j}d|||S )Nz{} {} {})lhsr<   rhsr   r   rel_opformat)r   r   r  r  lhs_coderhs_codeopr   r   r   _print_Relational  s    

z!RustCodePrinter._print_Relationalc                 C  s`   |j }tj}tj}tt|jD ]}||j| | 7 }||| 9 }qd| |j	j
| |f S )N%s[%s])r   r   ZeroOnereversedr   rankr   r   r.   label)r   r   dimselemoffsetr   r   r   r   _print_Indexed  s   zRustCodePrinter._print_Indexedc                 C  s   |j jS r:   )r  r   r   r   r   r   
_print_Idx  r   zRustCodePrinter._print_Idxc                 C  r9   r:   )r   r   r   r   r   _print_Dummy  s   zRustCodePrinter._print_Dummyc                 C  r   )NEr   r   r   r   r   r   r   _print_Exp1  r   zRustCodePrinter._print_Exp1c                 C  r   )NPIr   r$  r   r   r   	_print_Pi  r   zRustCodePrinter._print_Pic                 C  r   )NINFINITYr   r$  r   r   r   _print_Infinity  r   zRustCodePrinter._print_Infinityc                 C  r   )NNEG_INFINITYr   r$  r   r   r   _print_NegativeInfinity  r   z'RustCodePrinter._print_NegativeInfinityc                 C  r   )Nrz   r   r$  r   r   r   _print_BooleanTrue  r   z"RustCodePrinter._print_BooleanTruec                 C  r   )Nra   r   r$  r   r   r   _print_BooleanFalse  r   z#RustCodePrinter._print_BooleanFalsec                 C  s   t | S r:   )r   r   r$  r   r   r   _print_bool  s   zRustCodePrinter._print_boolc                 C  r   )NNANr   r$  r   r   r   
_print_NaN  r   zRustCodePrinter._print_NaNc                 C  s   |j d jdkrtdg }t|j D ]G\}\}}|dkr(|d| |  n#|t|j d kr>|dkr>|d  d7  < n|d  d| | 7  < | |}|| |d	 q| jd
 red|S 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   z	if (%s) {r5   z else {z else if (%s) {r   inline 
)	r   r   
ValueError	enumerater   r   r   	_settingsjoin)r   r   r   r   eccode0r   r   r   _print_Piecewise  s   




z RustCodePrinter._print_Piecewisec                 C  s    ddl m} | |j|ddS )Nr   )	PiecewiseF)deep)sympy.functionsr<  r   rewrite)r   r   r<  r   r   r   
_print_ITE  s   zRustCodePrinter._print_ITEc                   s.   |j dkrdd fdd|D  S td)Nr5   z[%s]r   c                 3  r   r:   )r   )r   ar   r   r   r     r   z4RustCodePrinter._print_MatrixBase.<locals>.<genexpr>zLFull Matrix Support in Rust need Crates (https://crates.io/keywords/matrix).)r   r7  r4  )r   Ar   r   r   _print_MatrixBase  s   
z!RustCodePrinter._print_MatrixBasec                 C  r   r:   )r   )r   r   r   r   r   _print_SparseRepMatrix  r   z&RustCodePrinter._print_SparseRepMatrixc                 C  s"   d|j |j|j|j jd   f S )Nr  r5   )parentr   r   r   r   r   r   r   _print_MatrixElement  s   z$RustCodePrinter._print_MatrixElementc                   s"   t  |}|| jv rd| S |S )Nz(*%s))rx   _print_Symbolr   )r   r   r   r   r   r   rG    s   
zRustCodePrinter._print_Symbolc                 C  sh   ddl m} |j}|j}| jd r!||s||r!| ||S | |}| |}| d||f S )Nr   )IndexedBaser   z%s = %s)	sympy.tensor.indexedrH  r  r  r6  has_doprint_loopsr   r   )r   r   rH  r  r  r  r  r   r   r   _print_Assignment'  s   

z!RustCodePrinter._print_Assignmentc                 C  s   |  |jd }d||f S )Nr   z/(if (%s == 0.0) { 0.0 } else { (%s).signum() }))r   r   )r   r   r   r   r   r   _print_sign5  s   zRustCodePrinter._print_signc                 C  s"   |j st|tS |jrt|S |S r:   )r   r   r   r<   r   r   r   r   r   r   9  s
   
zRustCodePrinter._cast_to_floatc                 C  s$   || j v p|tv pt| d|dS )z Check if function ``name`` is either a known function or has its own
            printing method. Used to check if rewriting is possible.z	_print_{}F)r   r   getattrr  )r   r   r   r   r   
_can_print@  s   $zRustCodePrinter._can_printc                 C  sB   t  }t|tr|jr||j |jD ]
}|| |}q|S r:   )	r   r   r   is_Functionr  r   r   union_collect_functions)r   r   	functionsr   r   r   r   rR  I  s   

z"RustCodePrinter._collect_functionsc                   s^   t |ts|S  |} fdd j D }|D ]}||jd\}}|r,||}q|S )Nc                   s>   i | ]\}\}}  |rt fd d|D r|||fqS )c                 3  r   r:   )rO  )r   fr   r   r   r   [  r   zFRustCodePrinter._rewrite_known_functions.<locals>.<dictcomp>.<genexpr>)rO  all)r   r   target_frequired_fsr   r   r   
<dictcomp>W  s    
z<RustCodePrinter._rewrite_known_functions.<locals>.<dictcomp>)NN)r   r   rR  _rewriteable_functionsitemsr   r!   r?  )r   r   expression_functionsrewriteable_functionsr   rV  _r   r   r   _rewrite_known_functionsR  s   



z(RustCodePrinter._rewrite_known_functionsc           
        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v rG||	 q9||| 8 }|d|| |	f  ||| 7 }q9|S )z0Accepts a string of code or a list of code linesTr   z    ){r   z{
z(
)r   r   c                 S  s   g | ]}| d qS )z 	)lstripr   liner   r   r   
<listcomp>n  s    z/RustCodePrinter.indent_code.<locals>.<listcomp>c                       g | ]}t tt|j qS r   )r  r   mapendswithra  )	inc_tokenr   r   rc  p  s     c                   rd  r   )r  r   re  
startswithra  )	dec_tokenr   r   rc  q  s    r   )r   r3  z%s%s)r   r   r   
splitlinesr7  r5  r   )
r   code
code_linestabincreasedecreaseprettylevelnrb  r   )ri  rg  r   r   c  s*   



zRustCodePrinter.indent_coder:   )F)>r!   r"   r#   r$   printmethodlanguager	   r   r   r   r   r   r
   r   r   r   r   r   __annotations__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,  r-  r.  r0  r;  r@  rC  rD  rF  rG  rL  rM  r   rO  rR  r^  r   r   r   r   r   r   r     sx   
 
	3








			r   )&r$   
__future__r   	functoolsr   r   typingr   sympy.codegen.astr   r   r   r   r	   r
   
sympy.corer   r   r   r   sympy.core.exprr   sympy.core.numbersr   #sympy.functions.elementary.integersr   r   sympy.printing.codeprinterr   sympy.printing.precedencer   r   r&   r   r   r   r   r   r   r   r   r   <module>   s    ! 	!"#$%&'+,-l6