B
    ˜‘[Ž  ã               @   s‚   d 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 ddlmZ ddlmZ dd	d
„Zdd„ Zdd„ ZdS )z1Gosper's algorithm for hypergeometric summation. é    )Úprint_functionÚdivision)ÚSÚDummyÚsymbols)Úis_sequenceÚrange)ÚPolyÚparallel_poly_from_exprÚfactor)Úsolve)Ú	hypersimpTc             C   sT  t | |f|ddd\\}}}| ¡ | ¡  }}| ¡ | ¡  }	}
|j||	  }}tdƒ}t|| |||jd}| |
 |¡¡}t	| 
¡  ¡ ƒ}x(t	|ƒD ]}|jrª|dk r˜| |¡ q˜W xht|ƒD ]\}| |
 |
 ¡¡}| |¡}|
 | | ¡¡}
x(td|d ƒD ]}|| | ¡9 }qW qÂW | |¡}|sJ| ¡ }|
 ¡ }
| ¡ }||
|fS )a?  
    Compute the Gosper's normal form of ``f`` and ``g``.

    Given relatively prime univariate polynomials ``f`` and ``g``,
    rewrite their quotient to a normal form defined as follows:

    .. math::
        \frac{f(n)}{g(n)} = Z \cdot \frac{A(n) C(n+1)}{B(n) C(n)}

    where ``Z`` is an arbitrary constant and ``A``, ``B``, ``C`` are
    monic polynomials in ``n`` with the following properties:

    1. `\gcd(A(n), B(n+h)) = 1 \forall h \in \mathbb{N}`
    2. `\gcd(B(n), C(n+1)) = 1`
    3. `\gcd(A(n), C(n)) = 1`

    This normal form, or rational factorization in other words, is a
    crucial step in Gosper's algorithm and in solving of difference
    equations. It can be also used to decide if two hypergeometric
    terms are similar or not.

    This procedure will return a tuple containing elements of this
    factorization in the form ``(Z*A, B, C)``.

    Examples
    ========

    >>> from sympy.concrete.gosper import gosper_normal
    >>> from sympy.abc import n

    >>> gosper_normal(4*n+5, 2*(4*n+1)*(2*n+3), n, polys=False)
    (1/4, n + 3/2, n + 1/4)

    T)ZfieldÚ	extensionÚh)Údomainr   é   )r
   ÚLCZmonicZoner   r	   r   Z	resultantZcomposeÚsetZground_rootsÚkeysÚ
is_IntegerÚremoveÚsortedZgcdÚshiftZquor   Z
mul_groundÚas_expr)ÚfÚgÚnZpolysÚpÚqZoptÚaÚAÚbÚBÚCÚZr   ÚDÚRÚrootsÚrÚiÚdÚj© r,   ú4lib/python3.7/site-packages/sympy/concrete/gosper.pyÚgosper_normal   s0    #

r.   c             C   sÔ  t | |ƒ}|dkrdS | ¡ \}}t|||ƒ\}}}| d¡}t| ¡ ƒ}t| ¡ ƒ}	t| ¡ ƒ}
||	ksz| ¡ | ¡ krŒ|
t||	ƒ h}nJ|s¦|
| d tdƒh}n0|
| d | |d ¡| |d ¡ | ¡  h}x(t	|ƒD ]}|j
rò|dk rà| |¡ qàW |s
dS t|ƒ}td|d  td}| ¡ j|Ž }t|||d}|| d¡ ||  | }t| ¡ |ƒ}|dkrxdS | ¡  |¡}x$|D ]}||krŒ| |d¡}qŒW |tjkr¼dS | ¡ | | ¡  S dS )a  
    Compute Gosper's hypergeometric term for ``f``.

    Suppose ``f`` is a hypergeometric term such that:

    .. math::
        s_n = \sum_{k=0}^{n-1} f_k

    and `f_k` doesn't depend on `n`. Returns a hypergeometric
    term `g_n` such that `g_{n+1} - g_n = f_n`.

    Examples
    ========

    >>> from sympy.concrete.gosper import gosper_term
    >>> from sympy.functions import factorial
    >>> from sympy.abc import n

    >>> gosper_term((4*n + 1)*factorial(n)/factorial(2*n + 1), n)
    (-n - 1/2)/(n + 1/4)

    Néÿÿÿÿr   r   zc:%s)Úcls)r   )r   Zas_numer_denomr.   r   r   Zdegreer   ÚmaxZnthr   r   r   r   r   Z
get_domainZinjectr	   r   Úcoeffsr   ÚsubsZZero)r   r   r(   r   r   r    r"   r#   ÚNÚMÚKr%   r*   r2   r   ÚxÚHZsolutionZcoeffr,   r,   r-   Úgosper_termS   sD    

0


r9   c             C   s¸   d}t |ƒr|\}}}nd}t| |ƒ}|dkr2dS |r@| | }np| |d   ||¡| |  ||¡ }|tjkr°y(| |d   ||¡| |  ||¡ }W n tk
r®   d}Y nX t|ƒS )a.  
    Gosper's hypergeometric summation algorithm.

    Given a hypergeometric term ``f`` such that:

    .. math ::
        s_n = \sum_{k=0}^{n-1} f_k

    and `f(n)` doesn't depend on `n`, returns `g_{n} - g(0)` where
    `g_{n+1} - g_n = f_n`, or ``None`` if `s_n` can not be expressed
    in closed form as a sum of hypergeometric terms.

    Examples
    ========

    >>> from sympy.concrete.gosper import gosper_sum
    >>> from sympy.functions import factorial
    >>> from sympy.abc import i, n, k

    >>> f = (4*k + 1)*factorial(k)/factorial(2*k + 1)
    >>> gosper_sum(f, (k, 0, n))
    (-factorial(n) + 2*factorial(2*n + 1))/factorial(2*n + 1)
    >>> _.subs(n, 2) == sum(f.subs(k, i) for i in [0, 1, 2])
    True
    >>> gosper_sum(f, (k, 3, n))
    (-60*factorial(n) + factorial(2*n + 1))/(60*factorial(2*n + 1))
    >>> _.subs(n, 5) == sum(f.subs(k, i) for i in [3, 4, 5])
    True

    References
    ==========

    .. [1] Marko Petkovsek, Herbert S. Wilf, Doron Zeilberger, A = B,
           AK Peters, Ltd., Wellesley, MA, USA, 1997, pp. 73--100

    FTNr   )r   r9   r3   r   ZNaNÚlimitÚNotImplementedErrorr   )r   ÚkZ
indefiniter   r!   r   Úresultr,   r,   r-   Ú
gosper_sumŸ   s     %

$
(
r>   N)T)Ú__doc__Z
__future__r   r   Z
sympy.corer   r   r   Zsympy.core.compatibilityr   r   Zsympy.polysr	   r
   r   Zsympy.solversr   Zsympy.simplifyr   r.   r9   r>   r,   r,   r,   r-   Ú<module>   s   
HL