o
    e,                     @   s   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
 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 G dd dZG dd dZdS )    )oo)Eq)symbols)FiniteFieldQQRationalFieldFF)solve)is_sequence)as_int   )divisors)polynomial_congruencec                   @   s   e Zd ZdZd!ddZd"ddZdd	 Zd
d Zdd Zdd Z	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d S )#EllipticCurveaH  
    Create the following Elliptic Curve over domain.

    `y^{2} + a_{1} x y + a_{3} y = x^{3} + a_{2} x^{2} + a_{4} x + a_{6}`

    The default domain is ``QQ``. If no coefficient ``a1``, ``a2``, ``a3``,
    it create curve as following form.

    `y^{2} = x^{3} + a_{4} x + a_{6}`

    Examples
    ========

    References
    ==========

    .. [1] J. Silverman "A Friendly Introduction to Number Theory" Third Edition
    .. [2] https://mathworld.wolfram.com/EllipticDiscriminant.html
    .. [3] G. Hardy, E. Wright "An Introduction to the Theory of Numbers" Sixth Edition

    r   c                 C   s  |dkrt }nt|}t|j|||||f\}}}}}|| _|| _|d d|  }d| ||  }	|d d|  }
|d | d| |  || |  ||d   |d  }||	|
|f\| _| _| _| _	|d  | d|	d   d|
d   d| |	 |
  | _
|| _|| _|| _|| _|| _td\}}}|||| _| _| _t|d | || | |  || |d   |d ||d  |  || |d   ||d   | _t| jtrd| _d S t| jtrd | _d S d S )	Nr                  	   zx y z)r   r   mapconvert_domainmodulus_b2_b4_b6Z_b8_discrim_a1_a2_a3_a4_a6r   xyzr   _eq
isinstancer   _rankr   )selfa4a6a1a2a3r   domainb2Zb4Zb6Zb8r#   r$   r%    r1   LD:\Projects\ConvertPro\env\Lib\site-packages\sympy/ntheory/elliptic_curve.py__init__$   s2    88d

zEllipticCurve.__init__r   c                 C   s   t |||| S NEllipticCurvePoint)r)   r#   r$   r%   r1   r1   r2   __call__@   s   zEllipticCurve.__call__c                 C   s   t |rt|dkrd}n|d }|d d \}}nt|tr+|j|j|j}}}ntd| jdkr:|dkr:dS | j	
| j|| j|| j|iS )Nr   r   zInvalid point.r   T)r
   lenr'   r6   r#   r$   r%   
ValueErrorcharacteristicr&   subs)r)   pointZz1x1y1r1   r1   r2   __contains__C   s   
zEllipticCurve.__contains__c                 C   s   d | j| jS )Nz	E({}): {})formatr   r&   r)   r1   r1   r2   __repr__R   s   zEllipticCurve.__repr__c                 C   s   | j }|dkr	| S |dkrt| jd | jd | jd | jdS | jd d| j  }| jd  d| j | j  d| j  }td| d	| | jd
S )a)  
        Return minimal Weierstrass equation.

        Examples
        ========

        >>> from sympy.ntheory.elliptic_curve import EllipticCurve

        >>> e1 = EllipticCurve(-10, -20, 0, -1, 1)
        >>> e1.minimal()
        E(QQ): Eq(y**2*z, x**3 - 13392*x*z**2 - 1080432*z**3)

        r   r   r   )r-   r      $      ii)r   )r:   r   r   r   r   r   )r)   charc4Zc6r1   r1   r2   minimalU   s   $&zEllipticCurve.minimalc                 C   sr   | j }t }|dkr5t|D ]$}| jj| jj | j|| jdi}t	||}|D ]	}|
||f q(q|S td)a5  
        Return points of curve over Finite Field.

        Examples
        ========

        >>> from sympy.ntheory.elliptic_curve import EllipticCurve
        >>> e2 = EllipticCurve(1, 1, 1, 1, 1, modulus=5)
        >>> e2.points()
        {(0, 2), (1, 4), (2, 0), (2, 2), (3, 0), (3, 1), (4, 0)}

        r   zInfinitely many points)r:   setranger&   lhsrhsr;   r#   r%   r   addr9   )r)   rF   Zall_pticongruence_eqZsolnumr1   r1   r2   pointsl   s   "
zEllipticCurve.pointsc                 C   s|   g }| j tkrt| j| j|D ]	}|||f q| jj| jj | j|| j	di}t
|| jD ]	}|||f q2|S )z2Returns points on with curve where xcoordinate = xr   )r   r   r	   r&   r;   r#   appendrK   rL   r%   r   r:   )r)   r#   ptr$   rO   r1   r1   r2   points_x   s   
"zEllipticCurve.points_xc                 C   s   | j dkr	tdt| g}t| j| jd| jdiD ]}|j	r*|
| |d qt| jddD ]6}t|d }|d |krht| j| j|| jdiD ]}|j	sTqN| ||}| tkrg||| g qNq2|S )al  
        Return torsion points of curve over Rational number.

        Return point objects those are finite order.
        According to Nagell-Lutz theorem, torsion point p(x, y)
        x and y are integers, either y = 0 or y**2 is divisor
        of discriminent. According to Mazur's theorem, there are
        at most 15 points in torsion collection.

        Examples
        ========

        >>> from sympy.ntheory.elliptic_curve import EllipticCurve
        >>> e2 = EllipticCurve(-43, 166)
        >>> sorted(e2.torsion_points())
        [(-5, -16), (-5, 16), O, (3, -8), (3, 8), (11, -32), (11, 32)]

        r   z"No torsion point for Finite Field.r   T)	generatorg      ?r   )r:   r9   r6   point_at_infinityr	   r&   r;   r$   r%   Zis_rationalrR   r   discriminantintorderr   extend)r)   lxxrN   jpr1   r1   r2   torsion_points   s$   
  
zEllipticCurve.torsion_pointsc                 C   s
   | j  S )z
        Return domain characteristic.

        Examples
        ========

        >>> from sympy.ntheory.elliptic_curve import EllipticCurve
        >>> e2 = EllipticCurve(-43, 166)
        >>> e2.characteristic
        0

        )r   r:   rA   r1   r1   r2   r:         
zEllipticCurve.characteristicc                 C   s
   t | jS )z
        Return curve discriminant.

        Examples
        ========

        >>> from sympy.ntheory.elliptic_curve import EllipticCurve
        >>> e2 = EllipticCurve(0, 17)
        >>> e2.discriminant
        -124848

        )rX   r   rA   r1   r1   r2   rW      r`   zEllipticCurve.discriminantc                 C   s
   | j dkS )zE
        Return True if curve discriminant is equal to zero.
        r   )rW   rA   r1   r1   r2   is_singular   s   
zEllipticCurve.is_singularc                 C   s*   | j d d| j  }| j|d | j S )z
        Return curve j-invariant.

        Examples
        ========

        >>> from sympy.ntheory.elliptic_curve import EllipticCurve
        >>> e1 = EllipticCurve(-2, 0, 0, 1, 1)
        >>> e1.j_invariant
        1404928/389

        r   rC   r   )r   r   r   to_sympyr   )r)   rG   r1   r1   r2   j_invariant   s   zEllipticCurve.j_invariantc                 C   s   | j dkr	tdt|  S )z
        Number of points in Finite field.

        Examples
        ========

        >>> from sympy.ntheory.elliptic_curve import EllipticCurve
        >>> e2 = EllipticCurve(1, 0, modulus=19)
        >>> e2.order
        19

        r   Still not implemented)r:   NotImplementedErrorr8   rQ   rA   r1   r1   r2   rY      s   
zEllipticCurve.orderc                 C   s   | j dur| j S td)zj
        Number of independent points of infinite order.

        For Finite field, it must be 0.
        Nrd   )r(   re   rA   r1   r1   r2   rank   s   
zEllipticCurve.rankN)r   r   r   r   )r   )__name__
__module____qualname____doc__r3   r7   r?   rB   rH   rQ   rT   r_   propertyr:   rW   ra   rc   rY   rf   r1   r1   r1   r2   r      s,    

$




r   c                   @   sd   e Zd ZdZe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dS )r6   a  
    Point of Elliptic Curve

    Examples
    ========

    >>> from sympy.ntheory.elliptic_curve import EllipticCurve
    >>> e1 = EllipticCurve(-17, 16)
    >>> p1 = e1(0, -4, 1)
    >>> p2 = e1(1, 0)
    >>> p1 + p2
    (15, -56)
    >>> e3 = EllipticCurve(-1, 9)
    >>> e3(1, -3) * 3
    (664/169, 17811/2197)
    >>> (e3(1, -3) * 3).order()
    oo
    >>> e2 = EllipticCurve(-2, 0, 0, 1, 1)
    >>> p = e2(-1,1)
    >>> q = e2(0, -1)
    >>> p+q
    (4, 8)
    >>> p-q
    (1, 0)
    >>> 3*p-5*q
    (328/361, -2800/6859)
    c                 C   s   t ddd| S Nr   r   r5   )curver1   r1   r2   rV   (  s   z$EllipticCurvePoint.point_at_infinityc                 C   sN   |j j}||| _||| _||| _|| _| jj | _ | j| s%tdd S )Nz%The curve does not contain this point)r   r   r#   r$   r%   _curver?   r9   )r)   r#   r$   r%   rm   domr1   r1   r2   r3   ,  s   



zEllipticCurvePoint.__init__c                 C   sp  | j dkr|S |j dkr| S | j| j  | j| j  }}|j|j  |j|j  }}| jj}| jj}| jj}| jj}	| jj}
||krU|| ||  }|| ||  ||  }nC|| dkra| 	| jS d|d  d| |  |	 ||  || | d|   }|d  |	|  d|
  ||  || | d|   }|d ||  | | | }||  | | | }| ||dS )Nr   r   r   r   )
r%   r#   r$   rn   r   r   r    r!   r"   rV   )r)   r^   r=   r>   Zx2y2r,   r-   r.   r*   r+   ZslopeZyintZx3Zy3r1   r1   r2   __add__6  s*   

86zEllipticCurvePoint.__add__c                 C   s    | j | j| jf|j |j|jfk S r4   )r#   r$   r%   r)   otherr1   r1   r2   __lt__N  s    zEllipticCurvePoint.__lt__c                 C   sd   t |}| | j}|dkr|S |dk r|  |  S | }|r0|d@ r&|| }|dL }|| }|s|S rl   )r   rV   rn   )r)   nrr^   r1   r1   r2   __mul__Q  s   zEllipticCurvePoint.__mul__c                 C   s   | | S r4   r1   )r)   ru   r1   r1   r2   __rmul__`  s   zEllipticCurvePoint.__rmul__c                 C   s.   t | j| j | jj| j  | jj | j| jS r4   )r6   r#   r$   rn   r   r    r%   rA   r1   r1   r2   __neg__c  s   .zEllipticCurvePoint.__neg__c                 C   sX   | j dkrdS | jj}zd|| j|| jW S  ty#   Y nw d| j| jS )Nr   Oz({}, {}))r%   rn   r   r@   rb   r#   r$   	TypeError)r)   ro   r1   r1   r2   rB   f  s   
zEllipticCurvePoint.__repr__c                 C   s   |  | S r4   )rq   rr   r1   r1   r2   __sub__p  s   zEllipticCurvePoint.__sub__c                 C   s  | j dkrdS | jdkrdS | d }|j| j krdS d}| jtkrSt|j|jkrQt|j|jkrQ| | }|d7 }|j dkrA|S t|j|jkrQt|j|jks2tS |jj|jkr|jj|jkr| | }|d7 }|dkrotS |j dkrv|S |jj|jkr|jj|jksatS )z5
        Return point order n where nP = 0.

        r   r   r   r      )r%   r$   r   r   rX   r#   r   	numerator)r)   r^   rN   r1   r1   r2   rY   s  s2   


 
 
zEllipticCurvePoint.orderN)rg   rh   ri   rj   staticmethodrV   r3   rq   rt   rw   rx   ry   rB   r|   rY   r1   r1   r1   r2   r6     s    


r6   N)Zsympy.core.numbersr   Zsympy.core.relationalr   Zsympy.core.symbolr   Zsympy.polys.domainsr   r   r   r   Zsympy.solvers.solversr	   Zsympy.utilities.iterablesr
   Zsympy.utilities.miscr   Zfactor_r   Zresidue_ntheoryr   r   r6   r1   r1   r1   r2   <module>   s     