o
    8Va,                     @   s   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
mZmZ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 )    )as_intis_sequence)oo)Eq)symbols)FiniteFieldQQRationalFieldFF)solve   )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 )#EllipticCurvea>  
    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] http://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   domainZb2Zb4Zb6Zb8r#   r$   r%    r0   >/usr/lib/python3/dist-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%   r0   r0   r1   __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'   r5   r#   r$   r%   
ValueErrorcharacteristicr&   subs)r)   ZpointZz1x1y1r0   r0   r1   __contains__B   s   
zEllipticCurve.__contains__c                 C   s   d | j| jS )Nz	E({}): {})formatr   r&   r)   r0   r0   r1   __repr__Q   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   )r9   r   r   r   r   r   )r)   charc4Zc6r0   r0   r1   minimalT   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)r9   setranger&   lhsrhsr:   r#   r%   r   addr8   )r)   rD   Zall_pticongruence_eqZsolZnumr0   r0   r1   pointsk   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#   appendrI   rJ   r%   r   r9   )r)   r#   ptr$   rM   r0   r0   r1   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   )r9   r8   r5   point_at_infinityr   r&   r:   r$   r%   Zis_rationalrO   r   discriminantintorderr   extend)r)   lZxxrL   jpr0   r0   r1   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   r9   r?   r0   r0   r1   r9         
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

        )rU   r   r?   r0   r0   r1   rT      r\   zEllipticCurve.discriminantc                 C   s
   | j dkS )zE
        Return True if curve discriminant is equal to zero.
        r   )rT   r?   r0   r0   r1   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   rA   r   )r   r   r   to_sympyr   )r)   rE   r0   r0   r1   j_invariant   s   zEllipticCurve.j_invariantc                 C   s"   | j dkr	tdt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)r9   NotImplementedErrorr7   listrN   r?   r0   r0   r1   rV      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.
        Nr`   )r(   ra   r?   r0   r0   r1   rank   s   
zEllipticCurve.rankN)r   r   r   r   )r   )__name__
__module____qualname____doc__r2   r6   r=   r@   rF   rN   rQ   r[   propertyr9   rT   r]   r_   rV   rc   r0   r0   r0   r1   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 )r5   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   r4   )curver0   r0   r1   rS   '  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=   r8   )r)   r#   r$   r%   rj   domr0   r0   r1   r2   +  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$   rk   r   r   r    r!   r"   rS   )r)   rZ   r;   r<   Zx2Zy2r,   r-   r.   r*   r+   ZslopeZyintZx3Zy3r0   r0   r1   __add__5  s*   

86zEllipticCurvePoint.__add__c                 C   s    | j | j| jf|j |j|jfk S r3   )r#   r$   r%   r)   otherr0   r0   r1   __lt__M  s    zEllipticCurvePoint.__lt__c                 C   sd   t |}| | j}|dkr|S |dk r|  |  S | }|r0|d@ r&|| }|dL }|| }|s|S ri   )r   rS   rk   )r)   nrrZ   r0   r0   r1   __mul__P  s   zEllipticCurvePoint.__mul__c                 C   s   | | S r3   r0   )r)   rq   r0   r0   r1   __rmul___  s   zEllipticCurvePoint.__rmul__c                 C   s.   t | j| j | jj| j  | jj | j| jS r3   )r5   r#   r$   rk   r   r    r%   r?   r0   r0   r1   __neg__b  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%   rk   r   r>   r^   r#   r$   	TypeError)r)   rl   r0   r0   r1   r@   e  s   
zEllipticCurvePoint.__repr__c                 C   s   |  | S r3   )rm   rn   r0   r0   r1   __sub__o  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   rU   r#   r   	numerator)r)   rZ   rL   r0   r0   r1   rV   r  s2   


 
 
zEllipticCurvePoint.orderN)rd   re   rf   rg   staticmethodrS   r2   rm   rp   rs   rt   ru   r@   rx   rV   r0   r0   r0   r1   r5   
  s    


r5   N)Zsympy.core.compatibilityr   r   Zsympy.core.numbersr   Zsympy.core.relationalr   Zsympy.core.symbolr   Zsympy.polys.domainsr   r   r	   r
   Zsympy.solvers.solversr   Zfactor_r   Zresidue_ntheoryr   r   r5   r0   r0   r0   r1   <module>   s     