
    \h.                         S SK Jr  S SKJr  S SKJrJrJr  S SKJ	r	  SSK
JrJr  SSKJr   " S S	5      rSS jrSS jrg
)    )log)_randint)gcdinvertsqrt)as_int   )sieve
primerange)isprimec                   6    \ rS rSrSrS rS rS rS rS r	Sr
g	)
Point   aL  Montgomery form of Points in an elliptic curve.
In this form, the addition and doubling of points
does not need any y-coordinate information thus
decreasing the number of operations.
Using Montgomery form we try to perform point addition
and doubling in least amount of multiplications.

The elliptic curve used here is of the form
(E : b*y**2*z = x**3 + a*x**2*z + x*z**2).
The a_24 parameter is equal to (a + 2)/4.

References
==========

.. [1] Kris Gaj, Soonhak Kwon, Patrick Baier, Paul Kohlbrenner, Hoang Le, Mohammed Khaleeluddin, Ramakrishna Bachimanchi,
       Implementing the Elliptic Curve Method of Factoring in Reconfigurable Hardware,
       Cryptographic Hardware and Embedded Systems - CHES 2006 (2006), pp. 119-133,
       https://doi.org/10.1007/11894063_10
       https://www.hyperelliptic.org/tanja/SHARCS/talks06/Gaj.pdf

c                 4    Xl         X l        X0l        X@l        g)z
Initial parameters for the Point class.

Parameters
==========

x_cord : X coordinate of the Point
z_cord : Z coordinate of the Point
a_24 : Parameter of the elliptic curve in Montgomery form
mod : modulus
N)x_cordz_corda_24mod)selfr   r   r   r   s        I/var/www/auris/envauris/lib/python3.13/site-packages/sympy/ntheory/ecm.py__init__Point.__init__(   s     	    c                    U R                   UR                   :w  d  U R                  UR                  :w  a  gU R                  UR                  -  U R                  -  UR                  U R                  -  U R                  -  :H  $ )z=Two points are equal if X/Z of both points are equal
        Fr   r   r   r   )r   others     r   __eq__Point.__eq__9   sb     99

"dhh%))&;{{U\\)DHH4LL4;;&12 	2r   c                    U R                   U R                  -
  UR                   UR                  -   -  nU R                   U R                  -   UR                   UR                  -
  -  nX4-   X4-
  peUR                  U-  U-  U R                  -  nUR                   U-  U-  U R                  -  n[        XxU R                  U R                  5      $ )a  
Add two points self and Q where diff = self - Q. Moreover the assumption
is self.x_cord*Q.x_cord*(self.x_cord - Q.x_cord) != 0. This algorithm
requires 6 multiplications. Here the difference between the points
is already known and using this algorithm speeds up the addition
by reducing the number of multiplication required. Also in the
mont_ladder algorithm is constructed in a way so that the difference
between intermediate points is always equal to the initial point.
So, we always know what the difference between the point is.


Parameters
==========

Q : point on the curve in Montgomery form
diff : self - Q

Examples
========

>>> from sympy.ntheory.ecm import Point
>>> p1 = Point(11, 16, 7, 29)
>>> p2 = Point(13, 10, 7, 29)
>>> p3 = p2.add(p1, p1)
>>> p3.x_cord
23
>>> p3.z_cord
17
)r   r   r   r   r   )	r   Qdiffuvaddsubtr   r   s	            r   r$   	Point.addA   s    < [[4;;&AHH)<=[[4;;&AHH)<=E15Ts"S(4883t#d*TXX5VTYY99r   c                 h   [        U R                  U R                  -   SU R                  5      n[        U R                  U R                  -
  SU R                  5      nX-
  nX-  U R                  -  nX2U R                  U-  -   -  U R                  -  n[        XEU R                  U R                  5      $ )z
Doubles a point in an elliptic curve in Montgomery form.
This algorithm requires 5 multiplications.

Examples
========

>>> from sympy.ntheory.ecm import Point
>>> p1 = Point(11, 16, 7, 29)
>>> p2 = p1.double()
>>> p2.x_cord
13
>>> p2.z_cord
10
   )powr   r   r   r   r   )r   r"   r#   r!   r   r   s         r   doublePoint.doublef   s      dkk)1dhh7dkk)1dhh7utxx499T>)*TXX5VTYY99r   c                     U nU R                  5       n[        U5      SS  HM  nUS:X  a#  UR                  X 5      nUR                  5       nM,  UR                  X05      nUR                  5       nMO     U$ )av  
Scalar multiplication of a point in Montgomery form
using Montgomery Ladder Algorithm.
A total of 11 multiplications are required in each step of this
algorithm.

Parameters
==========

k : The positive integer multiplier

Examples
========

>>> from sympy.ntheory.ecm import Point
>>> p1 = Point(11, 16, 7, 29)
>>> p3 = p1.mont_ladder(3)
>>> p3.x_cord
23
>>> p3.z_cord
17
   N1)r*   binr$   )r   kr    Ris        r   mont_ladderPoint.mont_ladder}   sf    . KKMQAc	EE!NHHJEE!NHHJ  r   r   N)__name__
__module____qualname____firstlineno____doc__r   r   r$   r*   r3   __static_attributes__ r   r   r   r      s!    ,"2#:J:. r   r   Nc                 b   [        U5      n[        [        U5      US-  S-
  5      n[        R                  " U5        S/U-  nS/U-  nSn	[        SUS-   5       H$  n
U	[        U
[        [        X5      5      5      -  n	M&     / n[        USU-  -   USU-  -   SU-  5       HS  n[        USU-  -
  USU-  -   5       Vs1 s H  n[        X-
  5      S-	  iM     nnUR                  [        U5      5        MU     [        U5       GHt  nU" SU S-
  5      nUS-  S-
  U -  nSU-  U -  n[        USU 5      n [        UU-
  SU 5      SU-  U-   -  [        SU-  U-  U 5      -  U -  n[!        U[        USU 5      UU 5      nUR#                  U	5      n[        UR$                  U 5      nUS:w  a
  UU :w  a  Us  $ UU :X  a  M  UUS'   UR'                  5       nUR)                  UU5      US'   US   R*                  US   R$                  -  U -  US'   US   R*                  US   R$                  -  U -  US'   [        SU5       HI  nUUS-
     R)                  UUUS-
     5      UU'   UU   R*                  UU   R$                  -  U -  UU'   MK     SnUR#                  SU-  5      nUR#                  USU-  -
  5      nUR#                  USU-  -   5      nU H  nUR*                  UR$                  -  U -  nU HM  nUR*                  UU   R*                  -
  UR$                  UU   R$                  -   -  U-
  UU   -   nUU-  U -  nMO     UUR)                  UU5      nnM     [        U U5      nUS:w  d  GMj  UU :w  d  GMs  Us  $    g	s  snf ! [         a#    [        SU-  U-  U 5      nUU :X  a   GM  Us s  $ f = f)
ae  Returns one factor of n using
Lenstra's 2 Stage Elliptic curve Factorization
with Suyama's Parameterization. Here Montgomery
arithmetic is used for fast computation of addition
and doubling of points in elliptic curve.

Explanation
===========

This ECM method considers elliptic curves in Montgomery
form (E : b*y**2*z = x**3 + a*x**2*z + x*z**2) and involves
elliptic curve operations (mod N), where the elements in
Z are reduced (mod N). Since N is not a prime, E over FF(N)
is not really an elliptic curve but we can still do point additions
and doubling as if FF(N) was a field.

Stage 1 : The basic algorithm involves taking a random point (P) on an
elliptic curve in FF(N). The compute k*P using Montgomery ladder algorithm.
Let q be an unknown factor of N. Then the order of the curve E, |E(FF(q))|,
might be a smooth number that divides k. Then we have k = l * |E(FF(q))|
for some l. For any point belonging to the curve E, |E(FF(q))|*P = O,
hence k*P = l*|E(FF(q))|*P. Thus kP.z_cord = 0 (mod q), and the unknownn
factor of N (q) can be recovered by taking gcd(kP.z_cord, N).

Stage 2 : This is a continuation of Stage 1 if k*P != O. The idea utilize
the fact that even if kP != 0, the value of k might miss just one large
prime divisor of |E(FF(q))|. In this case we only need to compute the
scalar multiplication by p to get p*k*P = O. Here a second bound B2
restrict the size of possible values of p.

Parameters
==========

n : Number to be Factored. Assume that it is a composite number.
B1 : Stage 1 Bound. Must be an even number.
B2 : Stage 2 Bound. Must be an even number.
max_curve : Maximum number of curves generated

Returns
=======

integer | None : a non-trivial divisor of ``n``. ``None`` if not found

References
==========

.. [1] Carl Pomerance, Richard Crandall, Prime Numbers: A Computational Perspective,
       2nd Edition (2005), page 344, ISBN:978-0387252827
r(   r	   r            r-      N)r   minr   r
   extendr   r)   intr   rangeabsappendlistr   ZeroDivisionErrorr   r   r3   r   r*   r$   r   )nB1B2	max_curveseedrandintDbetaSr0   pdeltas_listrqdeltas_sigmar"   r#   u_3a24gr    Q2dWTr1   alphadeltafs                                  r   _ecm_one_factorrc      s   d tnG 	DHbAgk"A	LLO37D	
aA	A26"	SCB
O$$ # K2!8R!A#Xqs++5a!A#gq1Q3w+GH+Ga#ae*/+GH4<( ,
 91q5!AX\QuWM!Ql	
 a!eQ"AaC!G,VBsF1Ha-@@1DC #s1a|S!,MM!! 6a1fH!V !XXZvva|!Q4;;qt{{*a/QQ4;;qt{{*a/Qq!AQU8<<Aa!eH-AaDt{{1Q4;;.!3DG 
 MM!A#MM"qs(#MM"qs(#!FXXahh&!+E XX%/XX%/1389;?;GqSAI   aeeAqkqAq " 1I 6a1fH{  I  ! 	AcE!GQAAvH	s   =M<3/N"N.'N.-N.c                   ^^^	^
^ SSK Jm  [        U 5      n US-  S:w  d	  US-  S:w  a  [        S5      eSm[	        5       m
[
        R                  " ST5       H6  nX-  S:X  d  M  T
R                  U5        X-  S:X  d  M(  X-  n X-  S:X  a  M  M8     / mUUU	U
U4S jm	T	" U 5        T(       aF  TR                  5       n [        XX#U5      nUc  [        S5      eT	" U5        T	" X-  5        T(       a  MF  T
$ )	a  Performs factorization using Lenstra's Elliptic curve method.

This function repeatedly calls ``_ecm_one_factor`` to compute the factors
of n. First all the small factors are taken out using trial division.
Then ``_ecm_one_factor`` is used to compute one factor at a time.

Parameters
==========

n : Number to be Factored
B1 : Stage 1 Bound. Must be an even number.
B2 : Stage 2 Bound. Must be an even number.
max_curve : Maximum number of curves generated
seed : Initialize pseudorandom generator

Examples
========

>>> from sympy.ntheory import ecm
>>> ecm(25645121643901801)
{5394769, 4753701529}
>>> ecm(9804659461513846513)
{4641991, 2112166839943}
r	   )_perfect_powerr(   r   zboth bounds must be even順 c                    > [        U 5      (       a  TR                  U 5        g T" U T5      =n(       a  T" US   5      $ TR                  U 5        g )Nr   )r   r$   rF   )mresultTF_LIMITre   checkfactorsqueues     r   rk   ecm.<locals>.checkM  sF    1::KKN#Ax0060##Qr   zIncrease the bounds)
factor_re   r   
ValueErrorsetr
   r   r$   poprc   )rI   rJ   rK   rL   rM   primefactorrj   re   rk   rl   rm   s          @@@@@r   ecmru   '  s    2 (q	A	Av{b1fk344HeG!!!X.9>KK)q. )q. / E  
!H
IIK t<>233fak % Nr   )'  rf      N)rv   rf   rw   i  )mathr   sympy.core.randomr   sympy.external.gmpyr   r   r   sympy.utilities.miscr   generater
   r   	primetestr   r   rc   ru   r;   r   r   <module>r~      s3     & 1 1 ' ' L L^DN5r   