o
    oh-                     @   s   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 dd
lmZ G dd dZG dd dZdS )    )oo)symbols)FiniteFieldQQRationalFieldFF)Poly)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 )#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``,
    is given then it creates a curve with the 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   |d	| _t| jtrd| _d S t| jtrd | _d S d S )
Nr                  	   zx y z)domain)r   r   mapconvert_domainmodulus_b2_b4_b6_b8_discrim_a1_a2_a3_a4_a6r   xyzr   _poly
isinstancer   _rankr   )selfa4a6a1a2a3r   r   b2b4b6b8r%   r&   r'    r5   p/var/www/html/construction_image-detection-poc/venv/lib/python3.10/site-packages/sympy/ntheory/elliptic_curve.py__init__#   s2    88j

zEllipticCurve.__init__r   c                 C   s   t |||| S NEllipticCurvePoint)r+   r%   r&   r'   r5   r5   r6   __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dkS )Nr   r   zInvalid point.r   T)r
   lenr)   r:   r%   r&   r'   
ValueErrorcharacteristicr(   subs)r+   pointz1x1y1r5   r5   r6   __contains__B   s   
"zEllipticCurve.__contains__c                 C   
   | j  S r8   )r(   __repr__r+   r5   r5   r6   rF   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()
        Poly(-x**3 + 13392*x*z**2 + y**2*z + 1080432*z**3, x, y, z, domain='QQ')

        r   r   r   )r/   r      $      ii)r   )r>   r   r   r   r   r   )r+   charc4c6r5   r5   r6   minimalT   s   $&zEllipticCurve.minimalc                    sj   | j }t }|dkr1t|D ]  | j| j | jdij}t||}|	 fdd|D  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   c                 3   s    | ]} |fV  qd S r8   r5   ).0numir5   r6   	<genexpr>   s    z'EllipticCurve.points.<locals>.<genexpr>zInfinitely many points)r>   setranger(   r?   r%   r'   exprr   updater=   )r+   rK   all_ptcongruence_eqsolr5   rQ   r6   pointsk   s   
zEllipticCurve.pointsc                 C   sx   g }| j tkrt| j| j|D ]	}|||f q|S | j| j|| jdij}t	|| j
D ]	}|||f q0|S )z7Returns points on the curve for the given x-coordinate.r   )r   r   r	   r(   r?   r%   appendr'   rV   r   r>   )r+   r%   ptr&   rY   r5   r5   r6   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>   r=   r:   point_at_infinityr	   r(   r?   r&   r'   is_rationalr\   r   discriminantintorderr   extend)r+   lxxrR   jpr5   r5   r6   torsion_points   s$   
  
zEllipticCurve.torsion_pointsc                 C   rE   )z
        Return domain characteristic.

        Examples
        ========

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

        )r   r>   rG   r5   r5   r6   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

        )rc   r   rG   r5   r5   r6   rb      rk   zEllipticCurve.discriminantc                 C   s
   | j dkS )zE
        Return True if curve discriminant is equal to zero.
        r   )rb   rG   r5   r5   r6   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   rH   r   )r   r   r   to_sympyr   )r+   rL   r5   r5   r6   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>   NotImplementedErrorr<   r[   rG   r5   r5   r6   rd      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.
        Nro   )r*   rp   rG   r5   r5   r6   rank   s   
zEllipticCurve.rankN)r   r   r   r   )r   )__name__
__module____qualname____doc__r7   r;   rD   rF   rN   r[   r^   rj   propertyr>   rb   rl   rn   rd   rq   r5   r5   r5   r6   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 )r:   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   r9   )curver5   r5   r6   r`   '  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'   _curverD   r=   )r+   r%   r&   r'   rx   domr5   r5   r6   r7   +  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&   ry   r    r!   r"   r#   r$   r`   )r+   ri   rB   rC   x2y2r.   r/   r0   r,   r-   slopeyintx3y3r5   r5   r6   __add__5  s*   

86zEllipticCurvePoint.__add__c                 C   s    | j | j| jf|j |j|jfk S r8   )r%   r&   r'   r+   otherr5   r5   r6   __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 rw   )r   r`   ry   )r+   nrri   r5   r5   r6   __mul__P  s   zEllipticCurvePoint.__mul__c                 C   s   | | S r8   r5   )r+   r   r5   r5   r6   __rmul___  s   zEllipticCurvePoint.__rmul__c                 C   s.   t | j| j | jj| j  | jj | j| jS r8   )r:   r%   r&   ry   r    r"   r'   rG   r5   r5   r6   __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'   ry   r   formatrm   r%   r&   	TypeError)r+   rz   r5   r5   r6   rF   e  s   
zEllipticCurvePoint.__repr__c                 C   s   |  | S r8   )r   r   r5   r5   r6   __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   rc   r%   r   	numerator)r+   ri   rR   r5   r5   r6   rd   r  s2   


 
 
zEllipticCurvePoint.orderN)rr   rs   rt   ru   staticmethodr`   r7   r   r   r   r   r   rF   r   rd   r5   r5   r5   r6   r:   
  s    


r:   N)sympy.core.numbersr   sympy.core.symbolr   sympy.polys.domainsr   r   r   r   sympy.polys.polytoolsr   sympy.solvers.solversr	   sympy.utilities.iterablesr
   sympy.utilities.miscr   factor_r   residue_ntheoryr   r   r:   r5   r5   r5   r6   <module>   s     