
    Ed-              	          d 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 ddlmZmZ ddlmZmZm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  ddl!m"Z"m#Z# ddl$m%Z% ddl&m'Z' ddl(m)Z) ddl*m+Z+  G d d          Z, G d de,          Z-d Z. e-d d           Z/ edd g          Z0 edd g          Z1 ed          Z2 ed           Z3 ed!d" g          Z4 e- ee3          e3z   ee3                    Z5 e- ee4e3z            e3z  e4 ee4e3z            z            Z6e5e6fZ7 e-e2 ee3          z   ed#          z  e2 ee3          z  d$ %          Z8 e- ed#           ee3          z   ee3                    Z9 e-d& d'           Z: G d( d)e-          Z; e;e
e          Z< e;ee%          Z= e-d* d+           Z>d, d-d.Z?d/ Z@d0 ZA e-e@eA          ZB e- e e
e2           e
e3          z              e"e2e3                    ZC e- e e d#e2           e d#e3          z              e#e2e3           ed#          z            ZDe<e>e/e8e9fZEeEeCeDfz   e7z   ZFe=fZGd1S )2a  
Classes and functions useful for rewriting expressions for optimized code
generation. Some languages (or standards thereof), e.g. C99, offer specialized
math functions for better performance and/or precision.

Using the ``optimize`` function in this module, together with a collection of
rules (represented as instances of ``Optimization``), one can rewrite the
expressions for this purpose::

    >>> from sympy import Symbol, exp, log
    >>> from sympy.codegen.rewriting import optimize, optims_c99
    >>> x = Symbol('x')
    >>> optimize(3*exp(2*x) - 3, optims_c99)
    3*expm1(2*x)
    >>> optimize(exp(2*x) - 1 - exp(-33), optims_c99)
    expm1(2*x) - exp(-33)
    >>> optimize(log(3*x + 3), optims_c99)
    log1p(x) + log(3)
    >>> optimize(log(2*x + 3), optims_c99)
    log(2*x + 3)

The ``optims_c99`` imported above is tuple containing the following instances
(which may be imported from ``sympy.codegen.rewriting``):

- ``expm1_opt``
- ``log1p_opt``
- ``exp2_opt``
- ``log2_opt``
- ``log2const_opt``


    )
expand_log)S)Wild)sign)explog)MaxMin)cossinsinc)Qask)log1plog2exp2expm1)MatrixSolve)UnevaluatedExpr)Pow)	logaddexp
logaddexp2)cosm1)Mul)MatrixSymbol)siftc                        e Zd ZdZddZd ZdS )Optimizationz Abstract base class for rewriting optimization.

    Subclasses should implement ``__call__`` taking an expression
    as argument.

    Parameters
    ==========
    cost_function : callable returning number
    priority : number

    N   c                 "    || _         || _        d S N)cost_functionpriority)selfr"   r#   s      7lib/python3.11/site-packages/sympy/codegen/rewriting.py__init__zOptimization.__init__@   s    *    c                 :    t          || j                  d         S )N)keyr   )sortedr"   )r$   argss     r%   cheapestzOptimization.cheapestD   s    d 2333A66r'   )Nr   )__name__
__module____qualname____doc__r&   r,    r'   r%   r   r   4   sA        
 
   7 7 7 7 7r'   r   c                   (     e Zd ZdZ fdZd Z xZS )ReplaceOptima   Rewriting optimization calling replace on expressions.

    Explanation
    ===========

    The instance can be used as a function on expressions for which
    it will apply the ``replace`` method (see
    :meth:`sympy.core.basic.Basic.replace`).

    Parameters
    ==========

    query :
        First argument passed to replace.
    value :
        Second argument passed to replace.

    Examples
    ========

    >>> from sympy import Symbol
    >>> from sympy.codegen.rewriting import ReplaceOptim
    >>> from sympy.codegen.cfunctions import exp2
    >>> x = Symbol('x')
    >>> exp2_opt = ReplaceOptim(lambda p: p.is_Pow and p.base == 2,
    ...     lambda p: exp2(p.exp))
    >>> exp2_opt(2**x)
    exp2(x)

    c                 V     t                      j        di | || _        || _        d S )Nr1   )superr&   queryvalue)r$   r6   r7   kwargs	__class__s       r%   r&   zReplaceOptim.__init__h   s2    ""6"""



r'   c                 B    |                     | j        | j                  S r!   )replacer6   r7   )r$   exprs     r%   __call__zReplaceOptim.__call__m   s    ||DJ
333r'   )r-   r.   r/   r0   r&   r=   __classcell__r9   s   @r%   r3   r3   H   sQ         >    
4 4 4 4 4 4 4r'   r3   c                     t          |d d          D ]-} ||           }|j        |} |                    | |          } .| S )a   Apply optimizations to an expression.

    Parameters
    ==========

    expr : expression
    optimizations : iterable of ``Optimization`` instances
        The optimizations will be sorted with respect to ``priority`` (highest first).

    Examples
    ========

    >>> from sympy import log, Symbol
    >>> from sympy.codegen.rewriting import optims_c99, optimize
    >>> x = Symbol('x')
    >>> optimize(log(x+3)/log(2) + log(x**2 + 1), optims_c99)
    log1p(x**2) + log2(x + 3)

    c                     | j         S r!   )r#   )opts    r%   <lambda>zoptimize.<locals>.<lambda>   s    s| r'   T)r)   reverse)r*   r"   r,   )r<   optimizationsoptimnew_exprs       r%   optimizerH   q   s_    * +C+CTRRR 2 25;; 	2DD>>$11DDKr'   c                 &    | j         o
| j        dk    S )N   )is_Powbaseps    r%   rC   rC      s    ah&16Q; r'   c                 *    t          | j                  S r!   )r   r   rM   s    r%   rC   rC      s    d15kk r'   dc                     | j         S r!   )is_Dummyxs    r%   rC   rC      s    QZ r'   )
propertiesuc                 "    | j          o| j         S r!   )	is_numberis_AddrS   s    r%   rC   rC      s    _%EQX r'   vwnc                     | j         S r!   rX   rS   s    r%   rC   rC      s    Q[ r'   rJ   c                 .    |                      d           S )Nc                     | j         r| j        j        p.t          | t          t
          f          o| j        d         j         S )Nr   )rK   r   is_negative
isinstancer   r   r+   rX   es    r%   rC   z<lambda>.<locals>.<lambda>   s>    	&QU& 	Dq3+&&Bqvay/B+B r'   )count)r<   s    r%   rC   rC      s%    SWS]S]E ET T r'   r"   c                     t          | t                    o]| j        d         j        oKt	          | j        d         j                  dk    o(t          d | j        d         j        D                       S )Nr   rJ   c              3   @   K   | ]}t          |t                    V  d S r!   )rb   r   ).0ts     r%   	<genexpr>z<lambda>.<locals>.<genexpr>   s,      BBaz!S))BBBBBBr'   )rb   r   r+   rY   lenallls    r%   rC   rC      sm    z!S!! C6!9#Cqvay~&&!+C BB16!9>BBBBB r'   c           
          t          d | j        d         j        D              t          t          t	          d | j        d         j        D                                  z   S )Nc                 (    g | ]}|j         d          S r   r+   ri   rd   s     r%   
<listcomp>z<lambda>.<locals>.<listcomp>   s    000AafQi000r'   r   c                 (    g | ]}|j         d          S rr   rs   rt   s     r%   ru   z<lambda>.<locals>.<listcomp>   s    :::aq	:::r'   )r	   r+   r   r   r
   rn   s    r%   rC   rC      sZ    000001c#::16!9>:::;<<==	> r'   c                   :     e Zd ZdZd fd	Zd Zd Z fdZ xZS )FuncMinusOneOptima  Specialization of ReplaceOptim for functions evaluating "f(x) - 1".

    Explanation
    ===========

    Numerical functions which go toward one as x go toward zero is often best
    implemented by a dedicated function in order to avoid catastrophic
    cancellation. One such example is ``expm1(x)`` in the C standard library
    which evaluates ``exp(x) - 1``. Such functions preserves many more
    significant digits when its argument is much smaller than one, compared
    to subtracting one afterwards.

    Parameters
    ==========

    func :
        The function which is subtracted by one.
    func_m_1 :
        The specialized function evaluating ``func(x) - 1``.
    opportunistic : bool
        When ``True``, apply the transformation as long as the magnitude of the
        remaining number terms decreases. When ``False``, only apply the
        transformation if it completely eliminates the number term.

    Examples
    ========

    >>> from sympy import symbols, exp
    >>> from sympy.codegen.rewriting import FuncMinusOneOptim
    >>> from sympy.codegen.cfunctions import expm1
    >>> x, y = symbols('x y')
    >>> expm1_opt = FuncMinusOneOptim(exp, expm1)
    >>> expm1_opt(exp(x) + 2*exp(5*y) - 3)
    expm1(x) + 2*expm1(5*y)


    Tc                     dt                                          d | j        fd           || _        | _        || _        d S )N
   c                     | j         S r!   )rY   rc   s    r%   rC   z,FuncMinusOneOptim.__init__.<locals>.<lambda>   s    18 r'   c                 ^    |                                  |                               z  z
  S r!   )	count_opsre   )r<   func_m_1weights    r%   rC   z,FuncMinusOneOptim.__init__.<locals>.<lambda>   s(    DNN4D4DvdjjYaNbNbGb4b r'   rf   )r5   r&   replace_in_Addfuncr~   opportunistic)r$   r   r~   r   r   r9   s     ` @r%   r&   zFuncMinusOneOptim.__init__   sd    ++T-@'b'b'b'b'b 	 	d 	d 	d	 *r'   c                      t          |j        d d          \  }}t          |          }t          | fdd          \  }}|||fS )Nc                     | j         S r!   r^   args    r%   rC   z4FuncMinusOneOptim._group_Add_terms.<locals>.<lambda>   s    cm r'   Tbinaryc                 8    |                      j                  S r!   )hasr   r   r$   s    r%   rC   z4FuncMinusOneOptim._group_Add_terms.<locals>.<lambda>   s    37749;M;M r'   )r   r+   sum)r$   addnumbersnon_numnumsumterms_with_funcothers   `      r%   _group_Add_termsz"FuncMinusOneOptim._group_Add_terms   s^    *C*CDQQQW!%g/M/M/M/MVZ![![![--r'   c                                           |          \  }}}|dk    r|S g g }}|D ]#}|j        rWt          |j         fdd          \  }}	t	          |          dk    r$t	          |	          dk    r|d         |	d         }	}n$d}	n!|j         j        k    r|t          j        }	}nd}	|	|	j        rt          |	          t          |           k    rb j
        r$t          |	|z             t          |          k     }
n	|	|z   dk    }
|
r,||	z  }|                    |	  j        |j         z             |                    |           % |j        |g|||R  S )z1 passed as second argument to Basic.replace(...) r   c                 $    | j         j         k    S r!   )r   r   s    r%   rC   z2FuncMinusOneOptim.replace_in_Add.<locals>.<lambda>   s    sx49?T r'   Tr   r   N)r   is_Mulr   r+   rl   r   r   OnerX   r   r   absappendr~   )r$   rd   r   r   other_non_num_termssubstituted	untouched	with_funcr   coeffdo_substitutes   `          r%   r   z FuncMinusOneOptim.replace_in_Add   s   7;7L7LQ7O7O4!4Q; 	H!#RY( 	( 	(I 	"9>3T3T3T3T]abbbet99> !c%jjAo !"&q'58%DD EE49, 'e 	U_ 	ef9U 	% 6$'f$5$5F$CMM$)&LA$5M  eOF&&u]T]DI-F'FGGGY''''qvfM{MYM9LMMMMr'   c                     t                                          |          }t                                          |                                          }|                     ||          S r!   )r5   r=   factorr,   )r$   r<   alt1alt2r9   s       r%   r=   zFuncMinusOneOptim.__call__  sM    ww%%ww..}}T4(((r'   )T)	r-   r.   r/   r0   r&   r   r   r=   r>   r?   s   @r%   rx   rx      s        $ $L+ + + + + +. . .N N N@) ) ) ) ) ) ) ) )r'   rx   c                 ,    t          | t                    S r!   )rb   r   rc   s    r%   rC   rC     s    jC   r'   c                     t          |                     t          d                                         t          t          dz             t	          t                              S )Nc                 D    t          |                                           S r!   )r   r   r   s    r%   rC   z<lambda>.<locals>.<lambda>  s    SZZ\\** r'   r   )r   r;   r   _ur   rn   s    r%   rC   rC     sK    j**   ws2a4yy%))$$ r'   c                     | j         S r!   )	is_symbol)bs    r%   rC   rC     s     r'   )base_reqc                0     t           fdd           S )a   Creates an instance of :class:`ReplaceOptim` for expanding ``Pow``.

    Explanation
    ===========

    The requirements for expansions are that the base needs to be a symbol
    and the exponent needs to be an Integer (and be less than or equal to
    ``limit``).

    Parameters
    ==========

    limit : int
         The highest power which is expanded into multiplication.
    base_req : function returning bool
         Requirement on base for expansion to happen, default is to return
         the ``is_symbol`` attribute of the base.

    Examples
    ========

    >>> from sympy import Symbol, sin
    >>> from sympy.codegen.rewriting import create_expand_pow_optimization
    >>> x = Symbol('x')
    >>> expand_opt = create_expand_pow_optimization(3)
    >>> expand_opt(x**5 + x**3)
    x**5 + x*x*x
    >>> expand_opt(x**5 + x**3 + sin(x)**3)
    x**5 + sin(x)**3 + x*x*x
    >>> opt2 = create_expand_pow_optimization(3, base_req=lambda b: not b.is_Function)
    >>> opt2((x+1)**2 + sin(x)**2)
    sin(x)**2 + (x + 1)*(x + 1)

    c                 z    | j         o3 | j                  o#| j        j        ot	          | j                  k    S r!   )rK   rL   r   
is_Integerr   )rd   r   limits    r%   rC   z0create_expand_pow_optimization.<locals>.<lambda>A  s7    !(\xx//\AE4D\QUW\I\ r'   c                     | j         dk    r(t          t          | j        g| j         
 z  ddi          n*dt          t          | j        g| j          z  ddi          z  S )Nr   evaluateFr   )r   r   r   rL   rM   s    r%   rC   z0create_expand_pow_optimization.<locals>.<lambda>B  sf    HIPQ	 GOC16(AE6/CUCCDDDocQVHaeVOEuEEFFF r'   )r3   )r   r   s   ``r%   create_expand_pow_optimizationr     s2    F \\\\\	
 	
  r'   c                 &   | j         rt          | j                  dk    rq| j        \  }}|j        r`|j        d         dk    rO|j        }t          |t                    r3t          t          t          j        |j                                      S dS )NrJ   r   F)	is_MatMulrl   r+   
is_Inverseshaper   rb   r   boolr   r   fullrankr<   leftrightinv_args       r%   _matinv_predicater   H  s    ~ 7#di..A- 7ie? 	7u{1~2 	7hG'<00 7C
48 4 4556665r'   c                 D    | j         \  }}|j        }t          ||          S r!   )r+   r   r   r   s       r%   _matinv_transformr   S  s$    )KD%hGw&&&r'   N)Hr0   sympy.core.functionr   sympy.core.singletonr   sympy.core.symbolr   $sympy.functions.elementary.complexesr   &sympy.functions.elementary.exponentialr   r   (sympy.functions.elementary.miscellaneousr	   r
   (sympy.functions.elementary.trigonometricr   r   r   sympy.assumptionsr   r   sympy.codegen.cfunctionsr   r   r   r   sympy.codegen.matrix_nodesr   sympy.core.exprr   sympy.core.powerr   sympy.codegen.numpy_nodesr   r   sympy.codegen.scipy_nodesr   sympy.core.mulr   "sympy.matrices.expressions.matexprr   sympy.utilities.iterablesr   r   r3   rH   exp2_opt_dr   _v_w_n	sinc_opt1	sinc_opt2	sinc_optslog2_optlog2const_optlogsumexp_2terms_optrx   	expm1_opt	cosm1_opt	log1p_optr   r   r   
matinv_optlogaddexp_optlogaddexp2_opt
optims_c99optims_numpyoptims_scipyr1   r'   r%   <module>r      s   @ + * * * * * " " " " " " " " " " " " 5 5 5 5 5 5 = = = = = = = = ? ? ? ? ? ? ? ? E E E E E E E E E E $ $ $ $ $ $ $ $ = = = = = = = = = = = = 2 2 2 2 2 2 + + + + + +             ; ; ; ; ; ; ; ; + + + + + +       ; ; ; ; ; ; * * * * * *7 7 7 7 7 7 7 7(&4 &4 &4 &4 &4< &4 &4 &4R  < <&&  
T#//0111	T#EEFGGG	T#YY	T#YY	T#001222LCGGBJR 	 LC2JJrM2dd2b5kk> 	 	"	<33r77
33q66)2dd2hh; G G    SSVVDDHH_cc"gg66#|D D 	 	 X) X) X) X) X) X) X) X)v c5))	c5))	L  % % 	 7L6K ( ( ( ( (V	 	 	' ' ' \+->??
 SSRR1199R3D3DEEcc##a**SSBZZ"788**R:L:LSSQRVV:STT HhF
]N<<yH|r'   