a
    ž¬<bì  ã                   @   s   d dl mZ d dlmZ d dlmZmZ d dlmZ d dl	m
Z
 d dlmZmZmZ d dlmZ dd	„ Zddd„Zdd„ Zddd„Zdd„ ZdS )é    )Úreduce)Úprod)ÚigcdexÚigcd©Úisprime)ÚZZ)Úgf_crtÚgf_crt1Úgf_crt2©Úas_intc                 C   s   | |d kr| S | | S )zÔReturn the residual mod m such that it is within half of the modulus.

    >>> from sympy.ntheory.modular import symmetric_residue
    >>> symmetric_residue(1, 6)
    1
    >>> symmetric_residue(4, 6)
    -2
    é   © )ÚaÚmr   r   úe/Users/vegardjervell/Documents/master/model/venv/lib/python3.9/site-packages/sympy/ntheory/modular.pyÚsymmetric_residue   s    	r   FTc                    sœ   |r t tt| ƒƒ} t tt|ƒƒ}t|| tƒ‰ t| ƒ}|r‚t‡ fdd„t|| ƒD ƒƒs‚tt t|| ƒƒd|dœŽ‰ ˆ du rzˆ S ˆ \‰ }|r”t	ˆ |ƒ|fS ˆ |fS )ak  Chinese Remainder Theorem.

    The moduli in m are assumed to be pairwise coprime.  The output
    is then an integer f, such that f = v_i mod m_i for each pair out
    of v and m. If ``symmetric`` is False a positive integer will be
    returned, else \|f\| will be less than or equal to the LCM of the
    moduli, and thus f may be negative.

    If the moduli are not co-prime the correct result will be returned
    if/when the test of the result is found to be incorrect. This result
    will be None if there is no solution.

    The keyword ``check`` can be set to False if it is known that the moduli
    are coprime.

    Examples
    ========

    As an example consider a set of residues ``U = [49, 76, 65]``
    and a set of moduli ``M = [99, 97, 95]``. Then we have::

       >>> from sympy.ntheory.modular import crt

       >>> crt([99, 97, 95], [49, 76, 65])
       (639985, 912285)

    This is the correct result because::

       >>> [639985 % m for m in [99, 97, 95]]
       [49, 76, 65]

    If the moduli are not co-prime, you may receive an incorrect result
    if you use ``check=False``:

       >>> crt([12, 6, 17], [3, 4, 2], check=False)
       (954, 1224)
       >>> [954 % m for m in [12, 6, 17]]
       [6, 0, 2]
       >>> crt([12, 6, 17], [3, 4, 2]) is None
       True
       >>> crt([3, 6], [2, 5])
       (5, 6)

    Note: the order of gf_crt's arguments is reversed relative to crt,
    and that solve_congruence takes residue, modulus pairs.

    Programmer's note: rather than checking that all pairs of moduli share
    no GCD (an O(n**2) test) and rather than factoring all moduli and seeing
    that there is no factor in common, a check that the result gives the
    indicated residuals is performed -- an O(n) operation.

    See Also
    ========

    solve_congruence
    sympy.polys.galoistools.gf_crt : low level crt routine used by this routine
    c                 3   s"   | ]\}}|| ˆ | kV  qd S ©Nr   )Ú.0Úvr   ©Úresultr   r   Ú	<genexpr>[   ó    zcrt.<locals>.<genexpr>F)ÚcheckÚ	symmetricN)
ÚlistÚmapr   r	   r   r   ÚallÚzipÚsolve_congruencer   )r   r   r   r   Úmmr   r   r   Úcrt   s     :ÿr#   c                 C   s
   t | tƒS )zÓFirst part of Chinese Remainder Theorem, for multiple application.

    Examples
    ========

    >>> from sympy.ntheory.modular import crt1
    >>> crt1([18, 42, 6])
    (4536, [252, 108, 756], [0, 2, 0])
    )r
   r   )r   r   r   r   Úcrt1g   s    r$   c                 C   s,   t || |||tƒ}|r$t||ƒ|fS ||fS )zûSecond part of Chinese Remainder Theorem, for multiple application.

    Examples
    ========

    >>> from sympy.ntheory.modular import crt1, crt2
    >>> mm, e, s = crt1([18, 42, 6])
    >>> crt2([18, 42, 6], [0, 0, 0], mm, e, s)
    (0, 4536)
    )r   r   r   )r   r   r"   ÚeÚsr   r   r   r   r   Úcrt2u   s    r'   c                  O   s
  dd„ }| }|  dd¡}|  dd¡r¶dd„ |D ƒ}i }|D ]4\}}||; }||v rf||| kr: d	S q:|||< q:d
d„ | ¡ D ƒ}~tdd„ |D ƒƒr¶tt|Ž ƒ\}}t|||ddS d}|D ],}	|||	ƒ}|d	u rÚ q|\}
}|
| }
q¾|rþt|
|ƒ|fS |
|fS d	S )a  Compute the integer ``n`` that has the residual ``ai`` when it is
    divided by ``mi`` where the ``ai`` and ``mi`` are given as pairs to
    this function: ((a1, m1), (a2, m2), ...). If there is no solution,
    return None. Otherwise return ``n`` and its modulus.

    The ``mi`` values need not be co-prime. If it is known that the moduli are
    not co-prime then the hint ``check`` can be set to False (default=True) and
    the check for a quicker solution via crt() (valid when the moduli are
    co-prime) will be skipped.

    If the hint ``symmetric`` is True (default is False), the value of ``n``
    will be within 1/2 of the modulus, possibly negative.

    Examples
    ========

    >>> from sympy.ntheory.modular import solve_congruence

    What number is 2 mod 3, 3 mod 5 and 2 mod 7?

    >>> solve_congruence((2, 3), (3, 5), (2, 7))
    (23, 105)
    >>> [23 % m for m in [3, 5, 7]]
    [2, 3, 2]

    If you prefer to work with all remainder in one list and
    all moduli in another, send the arguments like this:

    >>> solve_congruence(*zip((2, 3, 2), (3, 5, 7)))
    (23, 105)

    The moduli need not be co-prime; in this case there may or
    may not be a solution:

    >>> solve_congruence((2, 3), (4, 6)) is None
    True

    >>> solve_congruence((2, 3), (5, 6))
    (5, 6)

    The symmetric flag will make the result be within 1/2 of the modulus:

    >>> solve_congruence((2, 3), (5, 6), symmetric=True)
    (-1, 6)

    See Also
    ========

    crt : high level routine implementing the Chinese Remainder Theorem

    c                    sœ   | \}}|\}}||| |  }}}t t|||gƒ‰ ‡ fdd„|||fD ƒ\}}}|dkr~t||ƒ\}	}
‰ ˆ dkrvdS ||	9 }|||  ||  }}||fS )zùReturn the tuple (a, m) which satisfies the requirement
        that n = a + i*m satisfy n = a1 + j*m1 and n = a2 = k*m2.

        References
        ==========

        .. [1] https://en.wikipedia.org/wiki/Method_of_successive_substitution
        c                    s   g | ]}|ˆ  ‘qS r   r   )r   Úi©Úgr   r   Ú
<listcomp>É   r   z5solve_congruence.<locals>.combine.<locals>.<listcomp>é   N)r   r   r   )Zc1Úc2Za1Úm1Za2Úm2r   ÚbÚcZinv_aÚ_r   r   r)   r   Úcombine¼   s    	z!solve_congruence.<locals>.combiner   Fr   Tc                 S   s    g | ]\}}t |ƒt |ƒf‘qS r   r   ©r   Úrr   r   r   r   r+   Ö   r   z$solve_congruence.<locals>.<listcomp>Nc                 S   s   g | ]\}}||f‘qS r   r   )r   r   r5   r   r   r   r+   ë   r   c                 s   s   | ]\}}t |ƒV  qd S r   r   r4   r   r   r   r   ñ   r   z#solve_congruence.<locals>.<genexpr>)r   r   )r   r,   )ÚgetÚitemsr   r   r    r#   r   )Zremainder_modulus_pairsÚhintr3   Zrmr   Zuniqr5   r   ÚrvZrmiÚnr   r   r   r!   ˆ   s8    4


r!   N)FT)F)Ú	functoolsr   Zsympy.core.mulr   Zsympy.core.numbersr   r   Zsympy.ntheory.primetestr   Zsympy.polys.domainsr   Zsympy.polys.galoistoolsr	   r
   r   Zsympy.utilities.miscr   r   r#   r$   r'   r!   r   r   r   r   Ú<module>   s   
N
