B
    [                 @   s  d 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mZ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mZmZ G d	d
 d
eZG dd deZdd Z edd dd Z!eddd gdZ"eddd gdZ#edZ$edZ%ee$e	e% e	d e$ee% dd dZ&ee	dee% e	e%Z'edd dd Z(dd Z)d d! Z*ed"d e*Z+ed#d d$d Z,d%d& Z-e+e,e!e&e'fZ.d'S )(a  
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) - 3, optims_c99)
    exp(2*x) - 3
    >>> 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``


    )absolute_importdivisionprint_function)teechain)	logAddexpMaxMinWildPow
expand_logDummy)sift)filterfalse)Mul)log1plog2exp2expm1c               @   s   e Zd ZdZdd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             C   s   || _ || _d S )N)cost_functionpriority)selfr   r    r   6lib/python3.7/site-packages/sympy/codegen/rewriting.py__init__7   s    zOptimization.__init__)Nr   )__name__
__module____qualname____doc__r   r   r   r   r   r   +   s   r   c                   s(   e Zd ZdZ fddZdd Z  ZS )ReplaceOptima   Rewriting optimization calling replace on expressions.

    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, Pow
    >>> 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                s"   t t| jf | || _|| _d S )N)superr#   r   queryvalue)r   r%   r&   kwargs)	__class__r   r   r   V   s    zReplaceOptim.__init__c             C   s   | | j| jS )N)replacer%   r&   )r   exprr   r   r   __call__[   s    zReplaceOptim.__call__)r   r    r!   r"   r   r+   __classcell__r   r   )r(   r   r#   <   s   r#   c                s^   xXt |dd ddD ]B  | } jdkr0|} qt fdd| |f\}}||kr|} qW | 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             S   s   | j S )N)r   )Zoptr   r   r   <lambda>s   s    zoptimize.<locals>.<lambda>T)keyreverseNc                s
     | S )N)r   )x)optimr   r   r-   x   s    )sortedr   map)r*   ZoptimizationsZnew_exprZbeforeZafterr   )r1   r   optimize_   s    
r4   c             C   s   | j o| jdkS )N   )is_Powbase)pr   r   r   r-      s    r-   c             C   s
   t | jS )N)r   r	   )r8   r   r   r   r-      s    dc             C   s   | j S )N)Zis_Dummy)r0   r   r   r   r-      s    )Z
propertiesuc             C   s   | j  o| j S )N)	is_numberis_Add)r0   r   r   r   r-      s    vwr5   c             C   s   |  dd S )Nc             S   s*   | j r| jjp(t| ttfo(| jd j S )Nr   )r6   r	   Zis_negative
isinstancer   r   argsr;   )er   r   r   r-      s    z<lambda>.<locals>.<lambda>)count)r*   r   r   r   r-      s   )r   c             C   sD   t | toB| jd joBt| jd jdkoBtdd | jd jD S )Nr   r5   c             s   s   | ]}t |tV  qd S )N)r?   r	   ).0tr   r   r   	<genexpr>   s    z<lambda>.<locals>.<genexpr>)r?   r   r@   r<   lenall)lr   r   r   r-      s   
c             C   s<   t dd | jd jD  tttdd | jd jD   S )Nc             S   s   g | ]}|j d  qS )r   )r@   )rC   rA   r   r   r   
<listcomp>   s    z<lambda>.<locals>.<listcomp>r   c             S   s   g | ]}|j d  qS )r   )r@   )rC   rA   r   r   r   rI      s    )r
   r@   r   r	   r   )rH   r   r   r   r-      s    c                sP   | j tdd dd\}}| }dd | D  | td  fdd S )	Nc             S   s   t  S )N)r   )argr   r   r   r-      s    z_try_expm1.<locals>.<lambda>T)r3   c             S   s   i | ]\}}||qS r   r   )rC   kr=   r   r   r   
<dictcomp>   s    z_try_expm1.<locals>.<dictcomp>r   c                s   t  |  jd S )Nr   )r   r@   )r9   )new_oldr   r   r-      s    )r)   r	   factoritems_dZxreplace)r*   Z	protectedZold_newZfactoredr   )rM   r   
_try_expm1   s    rQ   c             C   s   t | jdd dd\}}t |dd dd\}}t|}g d }}xN|D ]F}|rZ|| qF|| }	t|	}
|	|
kr~|| qFd}||
 qFW |s|| | jt|| S )Nc             S   s   | j S )N)r;   )rJ   r   r   r   r-      s    z_expm1_value.<locals>.<lambda>T)Zbinaryc             S   s
   |  tS )N)Zhasr	   )rJ   r   r   r   r-      s    F)r   r@   sumappendrQ   funcr   )rA   ZnumbersZnon_numZnon_num_expZnon_num_otherZnumsumZnew_exp_termsZdoneZexp_termZ
looking_atZattemptr   r   r   _expm1_value   s"    



rU   c             C   s   | j S )N)r<   )rA   r   r   r   r-      s    c             C   s
   t | tS )N)r?   r   )rA   r   r   r   r-      s    c             C   s(   t | tdd ttd ttS )Nc             S   s   t |  S )N)r   rN   )rJ   r   r   r   r-      s    z<lambda>.<locals>.<lambda>r   )r   r)   r   _ur   )rH   r   r   r   r-      s   c                s   t  fdddd S )a   Creates an instance of :class:`ReplaceOptim` for expanding ``Pow``.

    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.

    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 + x*x*x + sin(x)**3

    c                s    | j o| jjo| jjo| j kS )N)r6   r7   Z	is_symbolr	   
is_integer)rA   )limitr   r   r-      s    z0create_expand_pow_optimization.<locals>.<lambda>c             S   s   t | jg| j ddiS )NZevaluateF)r   r7   r	   )r8   r   r   r   r-      s    )r#   )rX   r   )rX   r   create_expand_pow_optimization   s    
rY   N)/r"   Z
__future__r   r   r   	itertoolsr   r   Zsympyr   r   r	   r
   r   r   r   r   r   Zsympy.utilities.iterablesr   Zsympy.core.compatibilityr   Zsympy.core.mulr   Zsympy.codegen.cfunctionsr   r   r   r   objectr   r#   r4   Zexp2_optrP   rV   Z_vZ_wZlog2_optZlog2const_optZlogsumexp_2terms_optrQ   rU   Z	expm1_optZ	log1p_optrY   Z
optims_c99r   r   r   r   <module>!   s<   ,#
*

 