
    XhZ:                         d dl mZ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          Z G d	 d
          Zd Zd Zd Zd Zd Zd ZddZddZdS )    )explog)_randint)	bit_scan1gcdinvertsqrt)_perfect_power)isprime)_sqrt_mod_prime_powerc                        e Zd Zd Zd Zd ZdS )SievePolynomialc                 j    || _         || _        |dz  | _        d|z  |z  | _        |dz  |z
  | _        dS )a4  This class denotes the sieve polynomial.
        Provide methods to compute `(a*x + b)**2 - N` and
        `a*x + b` when given `x`.

        Parameters
        ==========

        a : parameter of the sieve polynomial
        b : parameter of the sieve polynomial
        N : number to be factored

           N)aba2abb2)selfr   r   Ns       b/var/www/tools.fuzzalab.pt/emblema-extractor/venv/lib/python3.11/site-packages/sympy/ntheory/qs.py__init__zSievePolynomial.__init__
   s?     Q$A#a%Q$(    c                 &    | j         |z  | j        z   S N)r   r   r   xs     r   eval_uzSievePolynomial.eval_u   s    vax$&  r   c                 <    | j         |z  | j        z   |z  | j        z   S r   )r   r   r   r   s     r   eval_vzSievePolynomial.eval_v    s!    	DG#Q&00r   N)__name__
__module____qualname__r   r   r!    r   r   r   r   	   sA          &! ! !1 1 1 1 1r   r   c                       e Zd ZdZd ZdS )FactorBaseElemz7This class stores an element of the `factor_base`.
    c                 Z    || _         || _        || _        d| _        d| _        d| _        dS )z
        Initialization of factor_base_elem.

        Parameters
        ==========

        prime : prime number of the factor_base
        tmem_p : Integer square root of x**2 = n mod prime
        log_p : Compute Natural Logarithm of the prime
        N)primetmem_plog_psoln1soln2b_ainv)r   r)   r*   r+   s       r   r   zFactorBaseElem.__init__'   s4     

 

r   N)r"   r#   r$   __doc__r   r%   r   r   r'   r'   $   s-             r   r'   c                    ddl m} g }d\  }}|                    d|           D ]}t          ||dz
  dz  |          dk    r|dk    r|t	          |          dz
  }|dk    r|t	          |          dz
  }t          ||d          d         }t          t          |          d	z            }|                    t          |||                     |||fS )
a  Generate `factor_base` for Quadratic Sieve. The `factor_base`
    consists of all the points whose ``legendre_symbol(n, p) == 1``
    and ``p < num_primes``. Along with the prime `factor_base` also stores
    natural logarithm of prime and the residue n modulo p.
    It also returns the of primes numbers in the `factor_base` which are
    close to 1000 and 5000.

    Parameters
    ==========

    prime_bound : upper prime bound of the factor_base
    n : integer to be factored
    r   )sieve)NN   r   i  Ni     )
sympy.ntheory.generater1   
primerangepowlenr   roundr   appendr'   )	prime_boundnr1   factor_baseidx_1000idx_5000r)   residuer+   s	            r   _generate_factor_baser@   <   s    -,,,,,K#Hh!!![11 F Fq519"E**a//t|| 0{++a/t|| 0{++a/+Aua88;G#e**U*++E~eWeDDEEEX{**r   c              #     K   t          d| z            dz  t          |          z
  }|pd}|pt          |          dz
  }	 d\  }	}
}t          d          D ]}d}g }t          |          |k     r\d}|dk    s||v r |||          }|dk    ||v ||         j        }||z  }|                    |           t          |          |k     \t          t          |          |z
            }|&t          |dz
            t          |dz
            k     r|}
|}	|}|	}|
}g }|D ]\}||         j        }||         j        t          ||z  |          z  |z  }d|z  |k    r||z
  }|                    ||z  |z             ]t          |          }t          |||           }|D ]v|j        z  dk    rd_        t          |j                  fd|D             _        j        |z
  z  j        z  _        j         |z
  z  j        z  _        w|V  t          ddt          |          dz
  z            D ]}t          |          }d||dz   z	  dz  z  dz
  }|j        d|z  ||         z  z   }|j        }t          |||           }|D ]Tj        
j        |j        |         z  z
  j        z  _        j        |j        |         z  z
  j        z  _        U|V  )	a6   Generate sieve polynomials indefinitely.
    Information such as `soln1` in the `factor_base` associated with
    the polynomial is modified in place.

    Parameters
    ==========

    N : Number to be factored
    M : sieve interval
    factor_base : factor_base primes
    idx_1000 : index of prime number in the factor_base near 1000
    idx_5000 : index of prime number in the factor_base near to 5000
    randint : A callable that takes two integers (a, b) and returns a random integer
              n such that a <= n <= b, similar to `random.randint`.
    r   r   r2   T)NNN2   Nc                 0    g | ]}d |z  z  j         z  S r   )r)   ).0b_elema_invfbs     r   
<listcomp>z(_generate_polynomial.<locals>.<listcomp>   s(    CCCv6%"(2CCCr   )r   r7   ranger)   r9   r   absr*   r   sumr   r,   r.   r-   r   r   r   )r   Mr<   r=   r>   randint
approx_valstartendbest_abest_q
best_ratio_r   qrand_ppratioBvalq_lgammar   givneg_powrG   rH   s                              @@r   _generate_polynomialrb   Y   sv       QqS!c!ff$JME

,s;''!+C5%5"
r 	# 	#AAAa&&:%%kkVq[[$WUC00F kkVq[['-Q    a&&:%% A+,,E!S^^c*q.6I6I%I%I"
  	# 	#Cc"(C$+fQ#Xs.C.CCcIEw}}eHHQVE\""""FFAq!$$ 	; 	;B28|q  1bh''ECCCCCCCCBIry1}-9BH	zA~."(:BHH q!c!ffQh-(( 	 	A!A!A,!+,q0Gai!n$AA1a((A! H H8#Hwry|';;rxGHwry|';;rxGGGGGk5r   c                 T   dgd| z  dz   z  }|D ]}|j         
t          | |j         z   |j        z  d| z  |j                  D ]}||xx         |j        z  cc<   |j        dk    rWt          | |j        z   |j        z  d| z  |j                  D ]}||xx         |j        z  cc<   |S )a  Sieve Stage of the Quadratic Sieve. For every prime in the factor_base
    that does not divide the coefficient `a` we add log_p over the sieve_array
    such that ``-M <= soln1 + i*p <=  M`` and ``-M <= soln2 + i*p <=  M`` where `i`
    is an integer. When p = 2 then log_p is only added using
    ``-M <= soln1 + i*p <=  M``.

    Parameters
    ==========

    M : sieve interval
    factor_base : factor_base primes
    r   r   r2   )r,   rJ   r)   r+   r-   )rM   r<   sieve_arrayfactoridxs        r   _gen_sieve_arrayrg      s     #qsQw-K 	- 	-<!fl*fl:AaCNN 	- 	-C,<1!fl*fl:AaCNN 	- 	-C,	-r   c                     | dk     r| dz  } d}nd}t          |d          D ]T\  }}| |j        z  rd}| |j        z  } | |j        z  dk    r|dz  }| |j        z  } | |j        z  dk    |dz  r|d|z  z  }U|| fS )z Check if `num` is smooth with respect to the given `factor_base`
    and compute its factorization vector.

    Parameters
    ==========

    num : integer whose smootheness is to be checked
    factor_base : factor_base primes
    r   r2   r   )	enumerater)   )numr<   vecr_   rH   es         r   _check_smoothnessrn      s     Qwwr	;** 	 	2> 	BHn!!FABHC BHn!! q5 	16MC8Or   c                    t          |          t          |           dz  z   |z
  dz  }g }t                      }	d|d         j        z  }
t          ||           D ]\  }}||k     r|                    |          }t          ||          \  }}|dk    r,|                    |                    |          ||f           g||
k     rt          |          r| |z  dk    r|		                    |           |                    |          }||v r\|
                    |          \  }}}||z  t          ||           z  | z  }||z  |dz  z  }||z  }|                    |||f           |||f||<   ||	fS )a)  Trial division stage. Here we trial divide the values generetated
    by sieve_poly in the sieve interval and if it is a smooth number then
    it is stored in `smooth_relations`. Moreover, if we find two partial relations
    with same large prime then they are combined to form a smooth relation.
    First we iterate over sieve array and look for values which are greater
    than accumulated_val, as these values have a high chance of being smooth
    number. Then using these values we find smooth relations.
    In general, let ``t**2 = u*p modN`` and ``r**2 = v*p modN`` be two partial relations
    with the same large prime p. Then they can be combined ``(t*r/p)**2 = u*v modN``
    to form a smooth relation.

    Parameters
    ==========

    N : Number to be factored
    M : sieve interval
    factor_base : factor_base primes
    sieve_array : stores log_p values
    sieve_poly : polynomial from which we find smooth relations
    partial_relations : stores partial relations with one large prime
    ERROR_TERM : error term for accumulated_val
    r   r3      ri   r2   r   )r   setr)   rj   r!   rn   r9   r   r   addpopr   )r   rM   r<   rd   
sieve_polypartial_relations
ERROR_TERMaccumulated_valsmooth_relationsproper_factorpartial_relation_upper_boundr   r[   r`   rl   rk   uu_prevv_prevvec_prevs                       r   _trial_division_stager      s   . 1vvAq(:5>OEEM#&{2'<#< K!,, 5 53  a  $Q44S!88##Z%6%6q%9%91c$BCCCC///GCLL/3w!||!!#&&&!!!$$A'''+<+@+@+E+E(fHVC^^+a/fHQ&x ''As4444*+Q!#&]**r   c              #   t  K   d |D             }t          |          }dg|z  }t          |          D ]n}d|z  }t          |          D ]W}||         |z  x}	rH|	||         z  }
|||<   d||<   t          |dz   |          D ]}||         |z  r||xx         |
z  cc<    nXot          |||          D ]\  }}}|r	|d         |d         }}t          |||          D ]#\  }}}|r||z  r||d         z  }||d         z  }$t          |          }dt	          ||z
  |           x}cxk     r| k     rn |V  dS )a   Finds proper factor of N using fast gaussian reduction for modulo 2 matrix.

    Parameters
    ==========

    N : Number to be factored
    smooth_relations : Smooth relations vectors matrix
    col : Number of columns in the matrix

    Reference
    ==========

    .. [1] A fast algorithm for gaussian elimination over GF(2) and
    its implementation on the GAPP. Cetin K.Koc, Sarath N.Arachchige
    c                     g | ]
}|d          S rD   r%   )rE   
s_relations     r   rI   z _find_factor.<locals>.<listcomp>  s    ???
jm???r   Fr2   Tr   N)r7   rJ   zipisqrtr   )r   rx   colmatrixrowmarkposmr_   rX   add_coljmatrelr{   r`   m1mat1rel1r^   s                       r   _find_factorr     s       @?.>???F
f++C7S=DSzz 
 
Hs 	 	A1IM!q fQi-q	Qq1uc** - -Aay1} -q			W,			 4)9::  3 	1vs1v1!$0@AA 	 	NBd cDj T!WT!W!HHSQ]]"''''a'''''GGG r        c           	      B    t          t          | ||||                    S )a  Performs factorization using Self-Initializing Quadratic Sieve.
    In SIQS, let N be a number to be factored, and this N should not be a
    perfect power. If we find two integers such that ``X**2 = Y**2 modN`` and
    ``X != +-Y modN``, then `gcd(X + Y, N)` will reveal a proper factor of N.
    In order to find these integers X and Y we try to find relations of form
    t**2 = u modN where u is a product of small primes. If we have enough of
    these relations then we can form ``(t1*t2...ti)**2 = u1*u2...ui modN`` such that
    the right hand side is a square, thus we found a relation of ``X**2 = Y**2 modN``.

    Here, several optimizations are done like using multiple polynomials for
    sieving, fast changing between polynomials and using partial relations.
    The use of partial relations can speeds up the factoring by 2 times.

    Parameters
    ==========

    N : Number to be Factored
    prime_bound : upper bound for primes in the factor base
    M : Sieve Interval
    ERROR_TERM : Error term for checking smoothness
    seed : seed of random number generator

    Returns
    =======

    set(int) : A set of factors of N without considering multiplicity.
               Returns ``{N}`` if factorization fails.

    Examples
    ========

    >>> from sympy.ntheory import qs
    >>> qs(25645121643901801, 2000, 10000)
    {5394769, 4753701529}
    >>> qs(9804659461513846513, 2000, 10000)
    {4641991, 2112166839943}

    See Also
    ========

    qs_factor

    References
    ==========

    .. [1] https://pdfs.semanticscholar.org/5c52/8a975c1405bd35c65993abf5a4edb667c1db.pdf
    .. [2] https://www.rieselprime.de/ziki/Self-initializing_quadratic_sieve
    )rq   	qs_factor)r   r:   rM   rv   seeds        r   qsr   :  s#    b yKJ==>>>r   c           
         | dk     rt          d          i }g }i }| dz  dk    r(d}| dz  } | dz  dk    r| dz  } |dz  }| dz  dk    ||d<   t          |           rd|| <   |S t          | d          x}	r|	\  }
}|||
<   |S | }t          |          }t	          ||           \  }}}t          |          dz  dz  }t          | |||||          D ]w}t          ||          }t          | ||||||          \  }}||z  }|D ]0}||z  rd}||z  }||z  dk    r||z  }|dz  }||z  dk    |||<   1|t          |          k    r nxt          | |t          |          dz             D ]J}||z  dk    r?d}||z  }||z  dk    r||z  }|dz  }||z  dk    |||<   |dk    st          |          r nK|dk    rd||<   |S )a   Performs factorization using Self-Initializing Quadratic Sieve.

    Parameters
    ==========

    N : Number to be Factored
    prime_bound : upper bound for primes in the factor base
    M : Sieve Interval
    ERROR_TERM : Error term for checking smoothness
    seed : seed of random number generator

    Returns
    =======

    dict[int, int] : Factors of N.
                     Returns ``{N: 1}`` if factorization fails.
                     Note that the key is not always a prime number.

    Examples
    ========

    >>> from sympy.ntheory import qs_factor
    >>> qs_factor(1009 * 100003, 2000, 10000)
    {1009: 1, 100003: 1}

    See Also
    ========

    qs

    r   zN should be greater than 1r   r2      i   d   )

ValueErrorr   r
   r   r@   r7   rb   rg   r   r   )r   r:   rM   rv   r   factorsrx   ru   rm   resultr;   N_copyrN   r=   r>   r<   	thresholdr^   rd   s_relp_frX   re   s                          r   r   r   n  s   @ 	1uu5666G 	1uzz	a!eqjj!GAFA !eqjj 
qzz 
1%%%v 1
FtnnG&;K&K&K#HhK  3&+I!!QXxQQ  &q+66*1ak1N_akll
sE! 	 	Az AqLF1*//1Q 1*// GAJJ,----E . q"2C4D4Dq4HII 	 	F?aAvF6/Q&&6!Q 6/Q&&  GFO{{gfoo{{{Nr   N)r   r   )mathr   r   sympy.core.randomr   sympy.external.gmpyr   r   r   r	   r   sympy.ntheory.factor_r
   sympy.ntheory.primetestr   sympy.ntheory.residue_ntheoryr   r   r'   r@   rb   rg   rn   r   r   r   r   r%   r   r   <module>r      sr           & & & & & & E E E E E E E E E E E E 0 0 0 0 0 0 + + + + + + ? ? ? ? ? ?1 1 1 1 1 1 1 16       0+ + +:H H HV  6  8/+ /+ /+d* * *Z1? 1? 1? 1?hU U U U U Ur   