o
    ThZ:                     @   s   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 dZG d	d
 d
Zdd Zdd Zdd Zdd Zdd Zdd ZdddZdddZdS )    )explog)_randint)	bit_scan1gcdinvertsqrt)_perfect_power)isprime)_sqrt_mod_prime_powerc                   @   s$   e Zd Zdd Zdd Zdd ZdS )SievePolynomialc                 C   s6   || _ || _|d | _d| | | _|d | | _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   N r   Q/home/air/segue/gemini/back/venv/lib/python3.10/site-packages/sympy/ntheory/qs.py__init__
   s
   
zSievePolynomial.__init__c                 C   s   | j | | j S N)r   r   r   xr   r   r   eval_u   s   zSievePolynomial.eval_uc                 C   s   | j | | j | | j S r   )r   r   r   r   r   r   r   eval_v    s   zSievePolynomial.eval_vN)__name__
__module____qualname__r   r   r   r   r   r   r   r   	   s    r   c                   @   s   e Zd ZdZdd ZdS )FactorBaseElemz7This class stores an element of the `factor_base`.
    c                 C   s(   || _ || _|| _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#   r   r   r   r   '   s   
zFactorBaseElem.__init__N)r   r   r   __doc__r   r   r   r   r   r    $   s    r    c           	      C   s   ddl m} g }d\}}|d| D ]C}t||d d |dkrU|dkr.|du r.t|d }|dkr<|du r<t|d }t||dd }tt|d	 }|t	||| q|||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.generater(   
primerangepowlenr   roundr   appendr    )	prime_boundnr(   factor_baseidx_1000idx_5000r!   residuer#   r   r   r   _generate_factor_base<   s   
r7   c                 #   s   t d|  d t | }|pd}|pt|d }	 d\}	}
}tdD ]U}d}g }t ||k rZd}|dks9||v rF|||}|dks9||v s9|| j}||9 }|| t ||k s/tt || }|du srt|d t|d k rx|}
|}	|}q#|	}|
}g }|D ](}|| j}|| jt|| | | }d| |kr|| }||| |  qt	|}t
||| }|D ]5|j dkrd_qt|j  fdd	|D _ j|  j _ j |  j _q|V  tddt|d  D ]S}t|}d||d ? d  d }|jd| ||   }|j}t
||| }|D ]'jdu r,q"j|j|   j _j|j|   j _q"|V  qq)
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   r)   T)NNN2   Nc                    s   g | ]}d |   j  qS r   )r!   ).0b_elema_invfbr   r   
<listcomp>   s    z(_generate_polynomial.<locals>.<listcomp>)r   r.   ranger!   r0   r   absr"   r   sumr   r$   r&   r%   r   r   r   )r   Mr3   r4   r5   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_powr   r<   r   _generate_polynomialY   sr   



 
 rX   c                 C   s   dgd|  d  }|D ]D}|j du rqt| |j  |j d|  |jD ]}||  |j7  < q"|jdkr4qt| |j |j d|  |jD ]}||  |j7  < qCq|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   r)   N)r$   r@   r!   r#   r%   )rC   r3   sieve_arrayfactoridxr   r   r   _gen_sieve_array   s   
"
"r\   c                 C   s   | dk r| d9 } d}nd}t |dD ]2\}}| |j rqd}| |j } | |j dkr:|d7 }| |j } | |j dks*|d rD|d|> 7 }q|| 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   r)   r   )	enumerater!   )numr3   vecrU   r>   er   r   r   _check_smoothness   s"   



rb   c                 C   s,  t |t | d  | d }g }t }	d|d j }
t|| D ]q\}}||k r)q ||}t||\}}|dkrE|||||f q ||
k rt|r| | dkrY|		| q ||}||v r|
|\}}}|| t||  |  }|| |d  }||N }||||f q |||f||< q ||	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   r*      r]   r)   r   )r   setr!   r^   r   rb   r0   r   r
   addpopr   )r   rC   r3   rY   
sieve_polypartial_relations
ERROR_TERMaccumulated_valsmooth_relationsproper_factorpartial_relation_upper_boundr   rQ   rV   r`   r_   uu_prevv_prevvec_prevr   r   r   _trial_division_stage   s2   


rr   c                 c   sJ   dd |D }t |}dg| }t|D ]=}d|> }t|D ]2}|| |@  }	rQ|	|| A }
|||< d||< t|d |D ]}|| |@ rN||  |
N  < q> nqqt|||D ]I\}}}|raqY|d |d }}t|||D ]\}}}|r||@ r||d 9 }||d 9 }qpt|}dt|| |  }  k r| k rn qY|V  qYd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                 S   s   g | ]}|d  qS r9   r   )r:   
s_relationr   r   r   r?     s    z _find_factor.<locals>.<listcomp>Fr)   Tr   N)r.   r@   zipisqrtr   )r   rk   colmatrixrowmarkposmrU   rN   add_coljmatrelrn   rV   m1mat1rel1rT   r   r   r   _find_factor  s@   
	&r        c                 C   s   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
    )rd   	qs_factor)r   r1   rC   ri   seedr   r   r   qs:  s   1r   c              	   C   s  | dk rt di }g }i }| d dkr2d}| d } | d dkr.| d } |d7 }| d dks ||d< t| r<d|| < |S t| d }	rM|	\}
}|||
< |S | }t|}t|| \}}}t|d d }t| |||||D ]G}t||}t| ||||||\}}||7 }|D ]%}|| rqd}|| }|| dkr|| }|d7 }|| dks|||< q|t|kr nqlt	| |t|d D ]0}|| dkrd}|| }|| dkr|| }|d7 }|| dks|||< |dkst|r nq|dkrd||< |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   r)      i   d   )

ValueErrorr
   r	   r   r7   r.   rX   r\   rr   r   )r   r1   rC   ri   r   factorsrk   rh   ra   resultr2   N_copyrD   r4   r5   r3   	thresholdrT   rY   s_relp_frN   rZ   r   r   r   r   n  sp    

r   N)r   r   )mathr   r   sympy.core.randomr   sympy.external.gmpyr   r   r   r   ru   sympy.ntheory.factor_r	   sympy.ntheory.primetestr
   sympy.ntheory.residue_ntheoryr   r   r    r7   rX   r\   rb   rr   r   r   r   r   r   r   r   <module>   s     K2
-4