B
    }[s                 @   s  d dl 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mZ d dl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 d dlmZ d dlmZ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 deZ,G dd dee	e,Z-G dd de,Z.G dd de.Z/G dd de.Z0d%ddZ1G dd  d e,Z2G d!d" d"e2Z3G d#d$ d$e2Z4dS )&    )print_functiondivision)Basic)Mul)S	Singleton)DummySymbol)rangeinteger_typeswith_metaclassis_sequenceiterableordered)call_highest_priority)cacheit)sympify)Tuple)global_evaluate)lcmfactor)IntervalIntersection)flatten)Idx)simplify)expandc               @   s  e Zd ZdZdZdZedd Zdd Ze	dd	 Z
e	d
d Ze	dd Ze	dd Ze	dd Ze	dd Ze	dd Zedd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zed$d%d& Zd'd( Zed)d*d+ Zd,d- Zd.d/ Zed0d1d2 Zd3d4 Z d5d6 Z!d:d8d9Z"d7S );SeqBasezBase class for sequencesT   c          
   C   s0   y
| j }W n  tttfk
r*   tj}Y nX |S )z[Return start (if possible) else S.Infinity.

        adapted from Set._infimum_key
        )startNotImplementedErrorAttributeError
ValueErrorr   Infinity)exprr    r%   5lib/python3.7/site-packages/sympy/series/sequences.py
_start_key!   s    
zSeqBase._start_keyc             C   s   t | j|j}|j|jfS )zTReturns start and stop.

        Takes intersection over the two intervals.
        )r   intervalinfsup)selfotherr(   r%   r%   r&   _intersect_interval.   s    zSeqBase._intersect_intervalc             C   s   t d|  dS )z&Returns the generator for the sequencez(%s).genN)r    )r+   r%   r%   r&   gen6   s    zSeqBase.genc             C   s   t d|  dS )z-The interval on which the sequence is definedz(%s).intervalN)r    )r+   r%   r%   r&   r(   ;   s    zSeqBase.intervalc             C   s   t d|  dS )z:The starting point of the sequence. This point is includedz
(%s).startN)r    )r+   r%   r%   r&   r   @   s    zSeqBase.startc             C   s   t d|  dS )z8The ending point of the sequence. This point is includedz	(%s).stopN)r    )r+   r%   r%   r&   stopE   s    zSeqBase.stopc             C   s   t d|  dS )zLength of the sequencez(%s).lengthN)r    )r+   r%   r%   r&   lengthJ   s    zSeqBase.lengthc             C   s   dS )z-Returns a tuple of variables that are boundedr%   r%   )r+   r%   r%   r&   	variablesO   s    zSeqBase.variablesc                s   t  fdd jD S )aG  
        This method returns the symbols in the object, excluding those
        that take on a specific value (i.e. the dummy symbols).

        Examples
        ========

        >>> from sympy import SeqFormula
        >>> from sympy.abc import n, m
        >>> SeqFormula(m*n**2, (n, 0, 5)).free_symbols
        {m}
        c             3   s&   | ]}|j  jD ]
}|V  qqd S )N)free_symbols
differencer1   ).0ij)r+   r%   r&   	<genexpr>b   s    z'SeqBase.free_symbols.<locals>.<genexpr>)setargs)r+   r%   )r+   r&   r2   T   s    zSeqBase.free_symbolsc             C   s0   || j k s|| jkr&td|| jf | |S )z#Returns the coefficient at point ptzIndex %s out of bounds %s)r   r/   
IndexErrorr(   _eval_coeff)r+   ptr%   r%   r&   coeffe   s    zSeqBase.coeffc             C   s   t d| j d S )NzhThe _eval_coeff method should be added to%s to return coefficient so it is availablewhen coeff calls it.)r    func)r+   r<   r%   r%   r&   r;   l   s    zSeqBase._eval_coeffc             C   s<   | j tjkr| j}n| j }| j tjkr,d}nd}|||  S )a  Returns the i'th point of a sequence.

        If start point is negative infinity, point is returned from the end.
        Assumes the first point to be indexed zero.

        Examples
        =========

        >>> from sympy import oo
        >>> from sympy.series.sequences import SeqPer

        bounded

        >>> SeqPer((1, 2, 3), (-10, 10))._ith_point(0)
        -10
        >>> SeqPer((1, 2, 3), (-10, 10))._ith_point(5)
        -5

        End is at infinity

        >>> SeqPer((1, 2, 3), (0, oo))._ith_point(5)
        5

        Starts at negative infinity

        >>> SeqPer((1, 2, 3), (-oo, 0))._ith_point(5)
        -5
           )r   r   NegativeInfinityr/   )r+   r5   initialstepr%   r%   r&   
_ith_pointr   s    zSeqBase._ith_pointc             C   s   dS )a   
        Should only be used internally.

        self._add(other) returns a new, term-wise added sequence if self
        knows how to add with other, otherwise it returns ``None``.

        ``other`` should only be a sequence object.

        Used within :class:`SeqAdd` class.
        Nr%   )r+   r,   r%   r%   r&   _add   s    zSeqBase._addc             C   s   dS )a*  
        Should only be used internally.

        self._mul(other) returns a new, term-wise multiplied sequence if self
        knows how to multiply with other, otherwise it returns ``None``.

        ``other`` should only be a sequence object.

        Used within :class:`SeqMul` class.
        Nr%   )r+   r,   r%   r%   r&   _mul   s    zSeqBase._mulc             C   s
   t | |S )a  
        Should be used when ``other`` is not a sequence. Should be
        defined to define custom behaviour.

        Examples
        ========

        >>> from sympy import S, oo, SeqFormula
        >>> from sympy.abc import n
        >>> SeqFormula(n**2).coeff_mul(2)
        SeqFormula(2*n**2, (n, 0, oo))

        Notes
        =====

        '*' defines multiplication of sequences with sequences only.
        )r   )r+   r,   r%   r%   r&   	coeff_mul   s    zSeqBase.coeff_mulc             C   s$   t |tstdt| t| |S )a;  Returns the term-wise addition of 'self' and 'other'.

        ``other`` should be a sequence.

        Examples
        ========

        >>> from sympy import S, oo, SeqFormula
        >>> from sympy.abc import n
        >>> SeqFormula(n**2) + SeqFormula(n**3)
        SeqFormula(n**3 + n**2, (n, 0, oo))
        zcannot add sequence and %s)
isinstancer   	TypeErrortypeSeqAdd)r+   r,   r%   r%   r&   __add__   s    
zSeqBase.__add__rL   c             C   s   | | S )Nr%   )r+   r,   r%   r%   r&   __radd__   s    zSeqBase.__radd__c             C   s&   t |tstdt| t| | S )a:  Returns the term-wise subtraction of 'self' and 'other'.

        ``other`` should be a sequence.

        Examples
        ========

        >>> from sympy import S, oo, SeqFormula
        >>> from sympy.abc import n
        >>> SeqFormula(n**2) - (SeqFormula(n))
        SeqFormula(n**2 - n, (n, 0, oo))
        zcannot subtract sequence and %s)rH   r   rI   rJ   rK   )r+   r,   r%   r%   r&   __sub__   s    
zSeqBase.__sub__rN   c             C   s
   |  | S )Nr%   )r+   r,   r%   r%   r&   __rsub__   s    zSeqBase.__rsub__c             C   s
   |  dS )zNegates the sequence.

        Examples
        ========

        >>> from sympy import S, oo, SeqFormula
        >>> from sympy.abc import n
        >>> -SeqFormula(n**2)
        SeqFormula(-n**2, (n, 0, oo))
        r?   )rG   )r+   r%   r%   r&   __neg__   s    zSeqBase.__neg__c             C   s$   t |tstdt| t| |S )a  Returns the term-wise multiplication of 'self' and 'other'.

        ``other`` should be a sequence. For ``other`` not being a
        sequence see :func:`coeff_mul` method.

        Examples
        ========

        >>> from sympy import S, oo, SeqFormula
        >>> from sympy.abc import n
        >>> SeqFormula(n**2) * (SeqFormula(n))
        SeqFormula(n**3, (n, 0, oo))
        zcannot multiply sequence and %s)rH   r   rI   rJ   SeqMul)r+   r,   r%   r%   r&   __mul__   s    
zSeqBase.__mul__rR   c             C   s   | | S )Nr%   )r+   r,   r%   r%   r&   __rmul__  s    zSeqBase.__rmul__c             c   s.   x(t | jD ]}| |}| |V  qW d S )N)r
   r0   rD   r=   )r+   r5   r<   r%   r%   r&   __iter__  s    
zSeqBase.__iter__c                st   t |tr |} |S t |trp|j|j }}|d krBd}|d krP j} fddt|||j	phdD S d S )Nr   c                s   g | ]}   |qS r%   )r=   rD   )r4   r5   )r+   r%   r&   
<listcomp>%  s    z'SeqBase.__getitem__.<locals>.<listcomp>r@   )
rH   r   rD   r=   slicer   r/   r0   r
   rC   )r+   indexr   r/   r%   )r+   r&   __getitem__  s    




zSeqBase.__getitem__Nc             C   sD  ddl m} dd | d| D }t|}|dkr<|d }nt||d }g }xtd|d D ]}	d|	 }
g }x&t|	D ]}|||||	   qxW ||}| dkr^t||||	|
 }||
krt	|ddd }P g }x,t|	||	 D ]}|||||	   qW ||}|| |||
d kr^t	|ddd }P q^W |dkrX|S t|}	|	dkrrg dfS ||	d  ||	d   d||	d  ||	    }}xt|	d D ]r}||| ||  7 }x>t|	| d D ]*}||| ||  ||| d   8 }qW ||| ||d   8 }qW |tt
|t
| fS dS )	a  
        Finds the shortest linear recurrence that satisfies the first n
        terms of sequence of order `\leq` n/2 if possible.
        If d is specified, find shortest linear recurrence of order
        `\leq` min(d, n/2) if possible.
        Returns list of coefficients ``[b(1), b(2), ...]`` corresponding to the
        recurrence relation ``x(n) = b(1)*x(n-1) + b(2)*x(n-2) + ...``
        Returns ``[]`` if no recurrence is found.
        If gfvar is specified, also returns ordinary generating function as a
        function of gfvar.

        Examples
        ========

        >>> from sympy import sequence, sqrt, oo, lucas
        >>> from sympy.abc import n, x, y
        >>> sequence(n**2).find_linear_recurrence(10, 2)
        []
        >>> sequence(n**2).find_linear_recurrence(10)
        [3, -3, 1]
        >>> sequence(2**n).find_linear_recurrence(10)
        [2]
        >>> sequence(23*n**4+91*n**2).find_linear_recurrence(10)
        [5, -10, 10, -5, 1]
        >>> sequence(sqrt(5)*(((1 + sqrt(5))/2)**n - (-(1 + sqrt(5))/2)**(-n))/5).find_linear_recurrence(10)
        [1, 1]
        >>> sequence(x+y*(-2)**(-n), (n, 0, oo)).find_linear_recurrence(30)
        [1/2, 1/2]
        >>> sequence(3*5**n + 12).find_linear_recurrence(20,gfvar=x)
        ([6, -5], 3*(-21*x + 5)/((x - 1)*(5*x - 1)))
        >>> sequence(lucas(n)).find_linear_recurrence(15,gfvar=x)
        ([1, 1], (x - 2)/(x**2 + x - 1))
        r   )Matrixc             S   s   g | ]}t t|qS r%   )r   r   )r4   tr%   r%   r&   rU   K  s    z2SeqBase.find_linear_recurrence.<locals>.<listcomp>N   r@   r?   )Zsympy.matricesrY   lenminr
   appendZdetr   ZLUsolver   r   )r+   ndZgfvarrY   xZlxrZcoeffsll2Zmlistkmyr5   r6   r%   r%   r&   find_linear_recurrence(  sJ    "


2*zSeqBase.find_linear_recurrence)NN)#__name__
__module____qualname____doc__Zis_commutativeZ_op_prioritystaticmethodr'   r-   propertyr.   r(   r   r/   r0   r1   r2   r   r=   r;   rD   rE   rF   rG   rL   r   rM   rN   rO   rP   rR   rS   rT   rX   rh   r%   r%   r%   r&   r      s8   )r   c               @   s8   e Zd ZdZedd Zedd Zdd Zdd	 Zd
S )EmptySequencea  Represents an empty sequence.

    The empty sequence is available as a
    singleton as ``S.EmptySequence``.

    Examples
    ========

    >>> from sympy import S, SeqPer, oo
    >>> from sympy.abc import x
    >>> S.EmptySequence
    EmptySequence()
    >>> SeqPer((1, 2), (x, 0, 10)) + S.EmptySequence
    SeqPer((1, 2), (x, 0, 10))
    >>> SeqPer((1, 2)) * S.EmptySequence
    EmptySequence()
    >>> S.EmptySequence.coeff_mul(-1)
    EmptySequence()
    c             C   s   t jS )N)r   EmptySet)r+   r%   r%   r&   r(     s    zEmptySequence.intervalc             C   s   t jS )N)r   ZZero)r+   r%   r%   r&   r0     s    zEmptySequence.lengthc             C   s   | S )z"See docstring of SeqBase.coeff_mulr%   )r+   r=   r%   r%   r&   rG     s    zEmptySequence.coeff_mulc             C   s   t g S )N)iter)r+   r%   r%   r&   rT     s    zEmptySequence.__iter__N)	ri   rj   rk   rl   rn   r(   r0   rG   rT   r%   r%   r%   r&   ro   s  s
   ro   c               @   sX   e Zd ZdZedd Zedd Zedd Zedd	 Zed
d Z	edd Z
dS )SeqExpra  Sequence expression class.

    Various sequences should inherit from this class.

    Examples
    ========

    >>> from sympy.series.sequences import SeqExpr
    >>> from sympy.abc import x
    >>> s = SeqExpr((1, 2, 3), (x, 0, 10))
    >>> s.gen
    (1, 2, 3)
    >>> s.interval
    Interval(0, 10)
    >>> s.length
    11

    See Also
    ========

    sympy.series.sequences.SeqPer
    sympy.series.sequences.SeqFormula
    c             C   s
   | j d S )Nr   )r9   )r+   r%   r%   r&   r.     s    zSeqExpr.genc             C   s   t | jd d | jd d S )Nr@   r[   )r   r9   )r+   r%   r%   r&   r(     s    zSeqExpr.intervalc             C   s   | j jS )N)r(   r)   )r+   r%   r%   r&   r     s    zSeqExpr.startc             C   s   | j jS )N)r(   r*   )r+   r%   r%   r&   r/     s    zSeqExpr.stopc             C   s   | j | j d S )Nr@   )r/   r   )r+   r%   r%   r&   r0     s    zSeqExpr.lengthc             C   s   | j d d fS )Nr@   r   )r9   )r+   r%   r%   r&   r1     s    zSeqExpr.variablesN)ri   rj   rk   rl   rn   r.   r(   r   r/   r0   r1   r%   r%   r%   r&   rr     s   rr   c               @   sR   e Zd ZdZdddZedd Zedd Zd	d
 Zdd Z	dd Z
dd ZdS )SeqPera  Represents a periodic sequence.

    The elements are repeated after a given period.

    Examples
    ========

    >>> from sympy import SeqPer, oo
    >>> from sympy.abc import k

    >>> s = SeqPer((1, 2, 3), (0, 5))
    >>> s.periodical
    (1, 2, 3)
    >>> s.period
    3

    For value at a particular point

    >>> s.coeff(3)
    1

    supports slicing

    >>> s[:]
    [1, 2, 3, 1, 2, 3]

    iterable

    >>> list(s)
    [1, 2, 3, 1, 2, 3]

    sequence starts from negative infinity

    >>> SeqPer((1, 2, 3), (-oo, 0))[0:6]
    [1, 2, 3, 1, 2, 3]

    Periodic formulas

    >>> SeqPer((k, k**2, k**3), (k, 0, oo))[0:6]
    [0, 1, 8, 3, 16, 125]

    See Also
    ========

    sympy.series.sequences.SeqFormula
    Nc             C   s$  t |}dd }d\}}}|d kr8||dtj  }}}t|trvt|dkrZ|\}}}nt|dkrv||}|\}}t|ttfr|d ks|d krt	dt
| |tjkr|tjkrt	dt |||f}t|trt tt|}nt	d	| t|d
 |d tjkrtjS t| ||S )Nc             S   s(   | j }t| j dkr| S tdS d S )Nr@   re   )r2   r\   popr   )
periodicalfreer%   r%   r&   _find_x  s    zSeqPer.__new__.<locals>._find_x)NNNr      r[   zInvalid limits given: %sz/Both the start and end valuecannot be unboundedz6invalid period %s should be something like e.g (1, 2) r@   )r   r   r#   r   r   r\   rH   r	   r   r"   strrA   tupler   r   rp   ro   r   __new__)clsru   limitsrw   ra   r   r/   r%   r%   r&   r{     s.    


zSeqPer.__new__c             C   s
   t | jS )N)r\   r.   )r+   r%   r%   r&   period"  s    zSeqPer.periodc             C   s   | j S )N)r.   )r+   r%   r%   r&   ru   &  s    zSeqPer.periodicalc             C   sF   | j tjkr| j| | j }n|| j  | j }| j| | jd |S )Nr   )r   r   rA   r/   r~   ru   subsr1   )r+   r<   idxr%   r%   r&   r;   *  s    zSeqPer._eval_coeffc             C   s   t |tr| j| j }}|j|j }}t||}g }x6t|D ]*}|||  }	|||  }
||	|
  q>W | |\}}t|| jd ||fS dS )zSee docstring of SeqBase._addr   N)	rH   rs   ru   r~   r   r
   r^   r-   r1   )r+   r,   per1lper1per2lper2
per_lengthnew_perra   ele1ele2r   r/   r%   r%   r&   rE   1  s    

zSeqPer._addc             C   s   t |tr| j| j }}|j|j }}t||}g }x6t|D ]*}|||  }	|||  }
||	|
  q>W | |\}}t|| jd ||fS dS )zSee docstring of SeqBase._mulr   N)	rH   rs   ru   r~   r   r
   r^   r-   r1   )r+   r,   r   r   r   r   r   r   ra   r   r   r   r/   r%   r%   r&   rF   B  s    

zSeqPer._mulc                s,   t    fdd| jD }t|| jd S )z"See docstring of SeqBase.coeff_mulc                s   g | ]}|  qS r%   r%   )r4   ra   )r=   r%   r&   rU   V  s    z$SeqPer.coeff_mul.<locals>.<listcomp>r@   )r   ru   rs   r9   )r+   r=   Zperr%   )r=   r&   rG   S  s    zSeqPer.coeff_mul)N)ri   rj   rk   rl   r{   rn   r~   ru   r;   rE   rF   rG   r%   r%   r%   r&   rs     s   .
(rs   c               @   sF   e Zd ZdZdddZedd Zdd Zd	d
 Zdd Z	dd Z
dS )
SeqFormulaaa  Represents sequence based on a formula.

    Elements are generated using a formula.

    Examples
    ========

    >>> from sympy import SeqFormula, oo, Symbol
    >>> n = Symbol('n')
    >>> s = SeqFormula(n**2, (n, 0, 5))
    >>> s.formula
    n**2

    For value at a particular point

    >>> s.coeff(3)
    9

    supports slicing

    >>> s[:]
    [0, 1, 4, 9, 16, 25]

    iterable

    >>> list(s)
    [0, 1, 4, 9, 16, 25]

    sequence starts from negative infinity

    >>> SeqFormula(n**2, (-oo, 0))[0:6]
    [0, 1, 4, 9, 16, 25]

    See Also
    ========

    sympy.series.sequences.SeqPer
    Nc             C   s   t |}dd }d\}}}|d kr8||dtj  }}}t|trvt|dkrZ|\}}}nt|dkrv||}|\}}t|ttfr|d ks|d krt	dt
| |tjkr|tjkrt	dt |||f}t|d	 |d tjkrtjS t| ||S )
Nc             S   sB   | j }t| j dkr| S t| j dkr2tdS td|  d S )Nr@   r   re   z specify dummy variables for %s. If the formula contains more than one free symbol, a dummy variable should be supplied explicitly e.g., SeqFormula(m*n**2, (n, 0, 5)))r2   r\   rt   r   r"   )formularv   r%   r%   r&   rw     s    z#SeqFormula.__new__.<locals>._find_x)NNNr   rx   r[   zInvalid limits given: %sz/Both the start and end valuecannot be unboundedr@   )r   r   r#   r   r   r\   rH   r	   r   r"   ry   rA   r   rp   ro   r   r{   )r|   r   r}   rw   ra   r   r/   r%   r%   r&   r{     s&    

zSeqFormula.__new__c             C   s   | j S )N)r.   )r+   r%   r%   r&   r     s    zSeqFormula.formulac             C   s   | j d }| j||S )Nr   )r1   r   r   )r+   r<   r`   r%   r%   r&   r;     s    
zSeqFormula._eval_coeffc       	      C   s`   t |tr\| j| jd  }}|j|jd  }}|||| }| |\}}t||||fS dS )zSee docstring of SeqBase._addr   N)rH   r   r   r1   r   r-   )	r+   r,   form1v1form2v2r   r   r/   r%   r%   r&   rE     s    
zSeqFormula._addc       	      C   s`   t |tr\| j| jd  }}|j|jd  }}|||| }| |\}}t||||fS dS )zSee docstring of SeqBase._mulr   N)rH   r   r   r1   r   r-   )	r+   r,   r   r   r   r   r   r   r/   r%   r%   r&   rF     s    
zSeqFormula._mulc             C   s"   t |}| j| }t|| jd S )z"See docstring of SeqBase.coeff_mulr@   )r   r   r   r9   )r+   r=   r   r%   r%   r&   rG     s    
zSeqFormula.coeff_mul)N)ri   rj   rk   rl   r{   rn   r   r;   rE   rF   rG   r%   r%   r%   r&   r   Z  s   &
'		r   Nc             C   s*   t | } t| trt| |S t| |S dS )a   Returns appropriate sequence object.

    If ``seq`` is a sympy sequence, returns :class:`SeqPer` object
    otherwise returns :class:`SeqFormula` object.

    Examples
    ========

    >>> from sympy import sequence, SeqPer, SeqFormula
    >>> from sympy.abc import n
    >>> sequence(n**2, (n, 0, 5))
    SeqFormula(n**2, (n, 0, 5))
    >>> sequence((1, 2, 3), (n, 0, 5))
    SeqPer((1, 2, 3), (n, 0, 5))

    See Also
    ========

    sympy.series.sequences.SeqPer
    sympy.series.sequences.SeqFormula
    N)r   r   r   rs   r   )seqr}   r%   r%   r&   sequence  s    

r   c               @   sX   e Zd ZdZedd Zedd Zedd Zedd	 Zed
d Z	edd Z
dS )	SeqExprOpa  Base class for operations on sequences.

    Examples
    ========

    >>> from sympy.series.sequences import SeqExprOp, sequence
    >>> from sympy.abc import n
    >>> s1 = sequence(n**2, (n, 0, 10))
    >>> s2 = sequence((1, 2, 3), (n, 5, 10))
    >>> s = SeqExprOp(s1, s2)
    >>> s.gen
    (n**2, (1, 2, 3))
    >>> s.interval
    Interval(5, 10)
    >>> s.length
    6

    See Also
    ========

    sympy.series.sequences.SeqAdd
    sympy.series.sequences.SeqMul
    c             C   s   t dd | jD S )zjGenerator for the sequence.

        returns a tuple of generators of all the argument sequences.
        c             s   s   | ]}|j V  qd S )N)r.   )r4   ar%   r%   r&   r7     s    z SeqExprOp.gen.<locals>.<genexpr>)rz   r9   )r+   r%   r%   r&   r.     s    zSeqExprOp.genc             C   s   t dd | jD S )zeSequence is defined on the intersection
        of all the intervals of respective sequences
        c             s   s   | ]}|j V  qd S )N)r(   )r4   r   r%   r%   r&   r7     s    z%SeqExprOp.interval.<locals>.<genexpr>)r   r9   )r+   r%   r%   r&   r(     s    zSeqExprOp.intervalc             C   s   | j jS )N)r(   r)   )r+   r%   r%   r&   r     s    zSeqExprOp.startc             C   s   | j jS )N)r(   r*   )r+   r%   r%   r&   r/     s    zSeqExprOp.stopc             C   s   t tdd | jD S )z%Cumulative of all the bound variablesc             S   s   g | ]
}|j qS r%   )r1   )r4   r   r%   r%   r&   rU     s    z'SeqExprOp.variables.<locals>.<listcomp>)rz   r   r9   )r+   r%   r%   r&   r1     s    zSeqExprOp.variablesc             C   s   | j | j d S )Nr@   )r/   r   )r+   r%   r%   r&   r0   !  s    zSeqExprOp.lengthN)ri   rj   rk   rl   rn   r.   r(   r   r/   r1   r0   r%   r%   r%   r&   r     s   r   c               @   s,   e Zd ZdZdd Zedd Zdd ZdS )	rK   a  Represents term-wise addition of sequences.

    Rules:
        * The interval on which sequence is defined is the intersection
          of respective intervals of sequences.
        * Anything + :class:`EmptySequence` remains unchanged.
        * Other rules are defined in ``_add`` methods of sequence classes.

    Examples
    ========

    >>> from sympy import S, oo, SeqAdd, SeqPer, SeqFormula
    >>> from sympy.abc import n
    >>> SeqAdd(SeqPer((1, 2), (n, 0, oo)), S.EmptySequence)
    SeqPer((1, 2), (n, 0, oo))
    >>> SeqAdd(SeqPer((1, 2), (n, 0, 5)), SeqPer((1, 2), (n, 6, 10)))
    EmptySequence()
    >>> SeqAdd(SeqPer((1, 2), (n, 0, oo)), SeqFormula(n**2, (n, 0, oo)))
    SeqAdd(SeqFormula(n**2, (n, 0, oo)), SeqPer((1, 2), (n, 0, oo)))
    >>> SeqAdd(SeqFormula(n**3), SeqFormula(n**2))
    SeqFormula(n**3 + n**2, (n, 0, oo))

    See Also
    ========

    sympy.series.sequences.SeqMul
    c                s   | dtd }t|} fdd  |}dd |D }|sDtjS tdd |D tjkrbtjS |rpt|S tt	|t
j}tj| f| S )	Nevaluater   c                sP   t | tr,t | tr&tt | jg S | gS t| rDtt | g S tdd S )Nz2Input must be Sequences or  iterables of Sequences)rH   r   rK   summapr9   r   rI   )arg)_flattenr%   r&   r   J  s    

z SeqAdd.__new__.<locals>._flattenc             S   s   g | ]}|t jk	r|qS r%   )r   ro   )r4   r   r%   r%   r&   rU   V  s    z"SeqAdd.__new__.<locals>.<listcomp>c             s   s   | ]}|j V  qd S )N)r(   )r4   r   r%   r%   r&   r7   \  s    z!SeqAdd.__new__.<locals>.<genexpr>)getr   listr   ro   r   rp   rK   reducer   r   r'   r   r{   )r|   r9   kwargsr   r%   )r   r&   r{   C  s    

zSeqAdd.__new__c                s   d}x~|rxtt | D ]h\} d}xPt | D ]D\}||kr<q* }|dk	r* fdd| D }|| P q*W |r|} P qW qW t| dkr|  S t| ddS dS )a  Simplify :class:`SeqAdd` using known rules.

        Iterates through all pairs and ask the constituent
        sequences if they can simplify themselves with any other constituent.

        Notes
        =====

        adapted from ``Union.reduce``

        TFNc                s   g | ]}| fkr|qS r%   r%   )r4   r   )srZ   r%   r&   rU     s    z!SeqAdd.reduce.<locals>.<listcomp>r@   )r   )	enumeraterE   r^   r\   rt   rK   )r9   new_argsid1id2new_seqr%   )r   rZ   r&   r   g  s$    


zSeqAdd.reducec                s   t  fdd| jD S )z9adds up the coefficients of all the sequences at point ptc             3   s   | ]}|  V  qd S )N)r=   )r4   r   )r<   r%   r&   r7     s    z%SeqAdd._eval_coeff.<locals>.<genexpr>)r   r9   )r+   r<   r%   )r<   r&   r;     s    zSeqAdd._eval_coeffN)ri   rj   rk   rl   r{   rm   r   r;   r%   r%   r%   r&   rK   &  s   $$rK   c               @   s,   e Zd ZdZdd Zedd Zdd ZdS )	rQ   a   Represents term-wise multiplication of sequences.

    Handles multiplication of sequences only. For multiplication
    with other objects see :func:`SeqBase.coeff_mul`.

    Rules:
        * The interval on which sequence is defined is the intersection
          of respective intervals of sequences.
        * Anything \* :class:`EmptySequence` returns :class:`EmptySequence`.
        * Other rules are defined in ``_mul`` methods of sequence classes.

    Examples
    ========

    >>> from sympy import S, oo, SeqMul, SeqPer, SeqFormula
    >>> from sympy.abc import n
    >>> SeqMul(SeqPer((1, 2), (n, 0, oo)), S.EmptySequence)
    EmptySequence()
    >>> SeqMul(SeqPer((1, 2), (n, 0, 5)), SeqPer((1, 2), (n, 6, 10)))
    EmptySequence()
    >>> SeqMul(SeqPer((1, 2), (n, 0, oo)), SeqFormula(n**2))
    SeqMul(SeqFormula(n**2, (n, 0, oo)), SeqPer((1, 2), (n, 0, oo)))
    >>> SeqMul(SeqFormula(n**3), SeqFormula(n**2))
    SeqFormula(n**5, (n, 0, oo))

    See Also
    ========

    sympy.series.sequences.SeqAdd
    c                s   | dtd }t|} fdd  |}|s6tjS tdd |D tjkrTtjS |rbt|S tt	|t
j}tj| f| S )Nr   r   c                sR   t | tr.t | tr&tt | jg S | gS nt| rFtt | g S tdd S )Nz2Input must be Sequences or  iterables of Sequences)rH   r   rQ   r   r   r9   r   rI   )r   )r   r%   r&   r     s    

z SeqMul.__new__.<locals>._flattenc             s   s   | ]}|j V  qd S )N)r(   )r4   r   r%   r%   r&   r7     s    z!SeqMul.__new__.<locals>.<genexpr>)r   r   r   r   ro   r   rp   rQ   r   r   r   r'   r   r{   )r|   r9   r   r   r%   )r   r&   r{     s    

zSeqMul.__new__c                s   d}x~|rxtt | D ]h\} d}xPt | D ]D\}||kr<q* }|dk	r* fdd| D }|| P q*W |r|} P qW qW t| dkr|  S t| ddS dS )a  Simplify a :class:`SeqMul` using known rules.

        Iterates through all pairs and ask the constituent
        sequences if they can simplify themselves with any other constituent.

        Notes
        =====

        adapted from ``Union.reduce``

        TFNc                s   g | ]}| fkr|qS r%   r%   )r4   r   )r   rZ   r%   r&   rU     s    z!SeqMul.reduce.<locals>.<listcomp>r@   )r   )r   rF   r^   r\   rt   rQ   )r9   r   r   r   r   r%   )r   rZ   r&   r     s$    


zSeqMul.reducec             C   s&   d}x| j D ]}|||9 }qW |S )z<multiplies the coefficients of all the sequences at point ptr@   )r9   r=   )r+   r<   valr   r%   r%   r&   r;     s    zSeqMul._eval_coeffN)ri   rj   rk   rl   r{   rm   r   r;   r%   r%   r%   r&   rQ     s   "$rQ   )N)5Z
__future__r   r   Zsympy.core.basicr   Zsympy.core.mulr   Zsympy.core.singletonr   r   Zsympy.core.symbolr   r	   Zsympy.core.compatibilityr
   r   r   r   r   r   Zsympy.core.decoratorsr   Zsympy.core.cacher   Zsympy.core.sympifyr   Zsympy.core.containersr   Zsympy.core.evaluater   Zsympy.polysr   r   Zsympy.sets.setsr   r   Zsympy.utilities.iterablesr   Zsympy.tensor.indexedr   Zsympy.simplifyr   Zsympyr   r   ro   rr   rs   r   r   r   rK   rQ   r%   r%   r%   r&   <module>   s8      Z%2 p
#9j