
    gM                     b   d Z ddlmZmZmZmZmZmZmZm	Z	m
Z
mZ ddlmZmZmZmZmZmZmZmZmZmZmZmZ ddlmZmZmZmZmZmZm Z m!Z!m"Z" ddl#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z) ddl*m+Z+m,Z, ddl-m.Z.m/Z/ d Z0d	 Z1d
 Z2d Z3d Z4d Z5d Z6d Z7d Z8d Z9d Z:d Z;ddZ<ddZ=ddZ>ddZ?ddZ@ddZAd ZBd ZCdS )z8Square-free decomposition algorithms and related tools.     )
dup_negdmp_negdup_subdmp_subdup_muldmp_muldup_quodmp_quodup_mul_grounddmp_mul_ground)	dup_stripdup_LCdmp_ground_LC
dmp_zero_p
dmp_ground
dup_degree
dmp_degreedmp_degree_indmp_degree_list	dmp_raise
dmp_injectdup_convert)	dup_diffdmp_diffdmp_diff_in	dup_shift	dmp_shift	dup_monicdmp_ground_monicdup_primitivedmp_ground_primitive)dup_inner_gcddmp_inner_gcddup_gcddmp_gcddmp_resultantdmp_primitive)gf_sqf_listgf_sqf_part)MultivariatePolynomialErrorDomainErrorc                 b    t          d |D                       }|t          |           k    sJ dS )z=Sanity check the degrees of a computed factorization in K[x].c              3   @   K   | ]\  }}|t          |          z  V  d S )N)r   ).0facks      S/var/www/html/ai-engine/env/lib/python3.11/site-packages/sympy/polys/sqfreetools.py	<genexpr>z%_dup_check_degrees.<locals>.<genexpr>$   s1      99hsAa*S//!999999    N)sumr   )fresultdegs      r1   _dup_check_degreesr8   "   s;    
99&999
9
9C*Q--r3   c                     dg|dz   z  }|D ]1\  }t          ||          }fdt          ||          D             }2t          |          t          | |          k    sJ dS )z=Sanity check the degrees of a computed factorization in K[X].r      c                 &    g | ]\  }}||z  z   S  r<   )r.   d1d2r0   s      r1   
<listcomp>z&_dmp_check_degrees.<locals>.<listcomp>-   s%    >>>BQV>>>r3   N)r   ziptuple)r5   ur6   degsr/   degs_facr0   s         @r1   _dmp_check_degreesrE   (   s    3!a%=D ? ?Q"3**>>>>#dH*=*=>>>;;/!Q////////r3   c           
      f    | sdS t          t          | t          | d|          |                     S )a  
    Return ``True`` if ``f`` is a square-free polynomial in ``K[x]``.

    Examples
    ========

    >>> from sympy.polys import ring, ZZ
    >>> R, x = ring("x", ZZ)

    >>> R.dup_sqf_p(x**2 - 2*x + 1)
    False
    >>> R.dup_sqf_p(x**2 - 1)
    True

    Tr:   )r   r$   r   )r5   Ks     r1   	dup_sqf_prH   1   s;       @tga!Q):):A>>????r3   c                     t          | |          rdS t          |dz             D ]P}t          | d|||          }t          ||          r&t          | |||          }t	          |||          dk    r dS QdS )a  
    Return ``True`` if ``f`` is a square-free polynomial in ``K[X]``.

    Examples
    ========

    >>> from sympy.polys import ring, ZZ
    >>> R, x,y = ring("x,y", ZZ)

    >>> R.dmp_sqf_p(x**2 + 2*x*y + y**2)
    False
    >>> R.dmp_sqf_p(x**2 + y**2)
    True

    Tr:   r   F)r   ranger   r%   r   )r5   rB   rG   ifpgcds         r1   	dmp_sqf_prN   G   s      !Q t1Q3ZZ 
 
Aq!Q''b! 	aQ""a##q((55 ) 4r3   c                 Z   |j         st          d          dt          |j                                        dd|j                  }}	 t          | d|d          \  }}t          ||d|j                  }t          ||j                  rnt          | |j
         |          |dz   }} `|| |fS )ag  
    Find a shift of `f` in `K[x]` that has square-free norm.

    The domain `K` must be an algebraic number field `k(a)` (see :ref:`QQ(a)`).

    Returns `(s,g,r)`, such that `g(x)=f(x-sa)`, `r(x)=\text{Norm}(g(x))` and
    `r` is a square-free polynomial over `k`.

    Examples
    ========

    We first create the algebraic number field `K=k(a)=\mathbb{Q}(\sqrt{3})`
    and rings `K[x]` and `k[x]`:

    >>> from sympy.polys import ring, QQ
    >>> from sympy import sqrt

    >>> K = QQ.algebraic_field(sqrt(3))
    >>> R, x = ring("x", K)
    >>> _, X = ring("x", QQ)

    We can now find a square free norm for a shift of `f`:

    >>> f = x**2 - 1
    >>> s, g, r = R.dup_sqf_norm(f)

    The choice of shift `s` is arbitrary and the particular values returned for
    `g` and `r` are determined by `s`.

    >>> s == 1
    True
    >>> g == x**2 - 2*sqrt(3)*x + 2
    True
    >>> r == X**4 - 8*X**2 + 4
    True

    The invariants are:

    >>> g == f.shift(-s*K.unit)
    True
    >>> g.norm() == r
    True
    >>> r.is_squarefree
    True

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

    This is part of Trager's algorithm for factorizing polynomials over
    algebraic number fields. In particular this function is algorithm
    ``sqfr_norm`` from [Trager76]_.

    See Also
    ========

    dmp_sqf_norm:
        Analogous function for multivariate polynomials over ``k(a)``.
    dmp_norm:
        Computes the norm of `f` directly without any shift.
    dup_ext_factor:
        Function implementing Trager's algorithm that uses this.
    sympy.polys.polytools.sqf_norm:
        High-level interface for using this function.
    ground domain must be algebraicr   r:   Tfront)is_Algebraicr+   r   modto_listdomr   r&   rH   r   unit)r5   rG   sgh_rs          r1   dup_sqf_normr]   i   s    B > =;<<<iAqu55qA3!Q...1!Q15))Q 	3Q++QUqA3 a7Nr3   c           
   #     K   |dz   }dg|z  }|| fV  |j         t          | |          }d t          t          |t	          |dz                                 D             }|D ]A}|                                }d||<   fd|D             }	t          | |	||          }
||
fV  Bd}	 |dz  }|g|z  } |z  g|z  }t          | |||          }||fV  .)z9Generate a sequence of candidate shifts for dmp_sqf_norm.r:   r   c                 $    g | ]\  }}|d k    |S )r   r<   )r.   dirK   s      r1   r?   z(_dmp_sqf_norm_shifts.<locals>.<listcomp>   s!    GGGQQ1r3   c                     g | ]} |z  	S r<   r<   )r.   s1ias     r1   r?   z(_dmp_sqf_norm_shifts.<locals>.<listcomp>   s    ###qbf###r3   )rW   r   sortedr@   rJ   copyr   )r5   rB   rG   ns0dvar_indicesrK   s1a1f1jsjajfjrc   s                  @r1   _dmp_sqf_norm_shiftsrq      s+      	
AA
qB
a%KKK 	
A 	1AGG&Qac

););"<"<GGGK   WWYY1#######q"a##"f 	
A	QS1WbdVaZq"a##"fr3   c                    |st          | |          \  }}}|g||fS |j        st          d          t          |j                                        |dz   d|j                  }t          | ||          D ]M\  }} t          | ||d          \  }}t          |||dz   |j                  }t          |||j                  r nN|| |fS )a  
    Find a shift of ``f`` in ``K[X]`` that has square-free norm.

    The domain `K` must be an algebraic number field `k(a)` (see :ref:`QQ(a)`).

    Returns `(s,g,r)`, such that `g(x_1,x_2,\cdots)=f(x_1-s_1 a, x_2 - s_2 a,
    \cdots)`, `r(x)=\text{Norm}(g(x))` and `r` is a square-free polynomial over
    `k`.

    Examples
    ========

    We first create the algebraic number field `K=k(a)=\mathbb{Q}(i)` and rings
    `K[x,y]` and `k[x,y]`:

    >>> from sympy.polys import ring, QQ
    >>> from sympy import I

    >>> K = QQ.algebraic_field(I)
    >>> R, x, y = ring("x,y", K)
    >>> _, X, Y = ring("x,y", QQ)

    We can now find a square free norm for a shift of `f`:

    >>> f = x*y + y**2
    >>> s, g, r = R.dmp_sqf_norm(f)

    The choice of shifts ``s`` is arbitrary and the particular values returned
    for ``g`` and ``r`` are determined by ``s``.

    >>> s
    [0, 1]
    >>> g == x*y - I*x + y**2 - 2*I*y - 1
    True
    >>> r == X**2*Y**2 + X**2 + 2*X*Y**3 + 2*X*Y + Y**4 + 2*Y**2 + 1
    True

    The required invariants are:

    >>> g == f.shift_list([-si*K.unit for si in s])
    True
    >>> g.norm() == r
    True
    >>> r.is_squarefree
    True

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

    This is part of Trager's algorithm for factorizing polynomials over
    algebraic number fields. In particular this function is a multivariate
    generalization of algorithm ``sqfr_norm`` from [Trager76]_.

    See Also
    ========

    dup_sqf_norm:
        Analogous function for univariate polynomials over ``k(a)``.
    dmp_norm:
        Computes the norm of `f` directly without any shift.
    dmp_ext_factor:
        Function implementing Trager's algorithm that uses this.
    sympy.polys.polytools.sqf_norm:
        High-level interface for using this function.
    rP   r:   r   TrQ   )r]   rS   r+   r   rT   rU   rV   rq   r   r&   rN   )r5   rB   rG   rX   rY   r\   rZ   r[   s           r1   dmp_sqf_normrs      s    D  q!$$1asAqy> =;<<<!%--//1q5!QU33A$Q1--  1!Q...1!QAqu--Q15!! 	E	 a7Nr3   c                     |j         st          d          t          |j                                        |dz   d|j                  }t          | ||d          \  }}t          |||dz   |j                  S )aE	  
    Norm of ``f`` in ``K[X]``, often not square-free.

    The domain `K` must be an algebraic number field `k(a)` (see :ref:`QQ(a)`).

    Examples
    ========

    We first define the algebraic number field `K = k(a) = \mathbb{Q}(\sqrt{2})`:

    >>> from sympy import QQ, sqrt
    >>> from sympy.polys.sqfreetools import dmp_norm
    >>> k = QQ
    >>> K = k.algebraic_field(sqrt(2))

    We can now compute the norm of a polynomial `p` in `K[x,y]`:

    >>> p = [[K(1)], [K(1),K.unit]]                  # x + y + sqrt(2)
    >>> N = [[k(1)], [k(2),k(0)], [k(1),k(0),k(-2)]] # x**2 + 2*x*y + y**2 - 2
    >>> dmp_norm(p, 1, K) == N
    True

    In higher level functions that is:

    >>> from sympy import expand, roots, minpoly
    >>> from sympy.abc import x, y
    >>> from math import prod
    >>> a = sqrt(2)
    >>> e = (x + y + a)
    >>> e.as_poly([x, y], extension=a).norm()
    Poly(x**2 + 2*x*y + y**2 - 2, x, y, domain='QQ')

    This is equal to the product of the expressions `x + y + a_i` where the
    `a_i` are the conjugates of `a`:

    >>> pa = minpoly(a)
    >>> pa
    _x**2 - 2
    >>> rs = roots(pa, multiple=True)
    >>> rs
    [sqrt(2), -sqrt(2)]
    >>> n = prod(e.subs(a, r) for r in rs)
    >>> n
    (x + y - sqrt(2))*(x + y + sqrt(2))
    >>> expand(n)
    x**2 + 2*x*y + y**2 - 2

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

    Given an algebraic number field `K = k(a)` any element `b` of `K` can be
    represented as polynomial function `b=g(a)` where `g` is in `k[x]`. If the
    minimal polynomial of `a` over `k` is `p_a` then the roots `a_1`, `a_2`,
    `\cdots` of `p_a(x)` are the conjugates of `a`. The norm of `b` is the
    product `g(a1) \times g(a2) \times \cdots` and is an element of `k`.

    As in [Trager76]_ we extend this norm to multivariate polynomials over `K`.
    If `b(x)` is a polynomial in `k(a)[X]` then we can think of `b` as being
    alternately a function `g_X(a)` where `g_X` is an element of `k[X][y]` i.e.
    a polynomial function with coefficients that are elements of `k[X]`. Then
    the norm of `b` is the product `g_X(a1) \times g_X(a2) \times \cdots` and
    will be an element of `k[X]`.

    See Also
    ========

    dmp_sqf_norm:
        Compute a shift of `f` so that the `\text{Norm}(f)` is square-free.
    sympy.polys.polytools.Poly.norm:
        Higher-level function that calls this.
    rP   r:   r   TrQ   )rS   r+   r   rT   rU   rV   r   r&   )r5   rB   rG   rY   rZ   r[   s         r1   dmp_normru   9  su    P > =;<<<!%--//1q5!QU33AaAT***DAqAq1uae,,,r3   c                     t          | ||j                  } t          | |j        |j                  }t          ||j        |          S )z3Compute square-free part of ``f`` in ``GF(p)[x]``. )r   rV   r)   rT   )r5   rG   rY   s      r1   dup_gf_sqf_partrw     s>    Aq!%  AAquae$$Aq!%###r3   c                      t          d          )z3Compute square-free part of ``f`` in ``GF(p)[X]``. +multivariate polynomials over finite fieldsNotImplementedErrorr5   rB   rG   s      r1   dmp_gf_sqf_partr}         
K
L
LLr3   c                 Z   |j         rt          | |          S | s| S |                    t          | |                    rt	          | |          } t          | t          | d|          |          }t          | ||          }|j        rt          ||          S t          ||          d         S )a  
    Returns square-free part of a polynomial in ``K[x]``.

    Examples
    ========

    >>> from sympy.polys import ring, ZZ
    >>> R, x = ring("x", ZZ)

    >>> R.dup_sqf_part(x**3 - 3*x - 2)
    x**2 - x - 2

    See Also
    ========

    sympy.polys.polytools.Poly.sqf_part
    r:   )is_FiniteFieldrw   is_negativer   r   r$   r   r	   is_Fieldr   r    )r5   rG   rM   sqfs       r1   dup_sqf_partr     s    $ 	 %q!$$$ }}VAq\\"" AqMM
!XaA&&
*
*C
!S!

Cz (a   S!$$Q''r3   c                    |st          | |          S |j        rt          | ||          S t          | |          r| S |                    t          | ||                    rt          | ||          } | }t          |dz             D ]%}t          |t          | d|||          ||          }&t          | |||          }|j        rt          |||          S t          |||          d         S )z
    Returns square-free part of a polynomial in ``K[X]``.

    Examples
    ========

    >>> from sympy.polys import ring, ZZ
    >>> R, x,y = ring("x,y", ZZ)

    >>> R.dmp_sqf_part(x**3 + 2*x**2*y + x*y**2)
    x**2 + x*y

    r:   )r   r   r}   r   r   r   r   rJ   r%   r   r
   r   r   r!   )r5   rB   rG   rM   rK   r   s         r1   dmp_sqf_partr     s
     "Aq!!! (q!Q'''!Q }}]1a++,, Aq!
C1Q3ZZ = =c;q!Q155q!<<
!S!Q

Cz 2Q***#CA..q11r3   Fc                 2   | }t          | ||j                  } t          | |j        |j        |          \  }}t	          |          D ]#\  }\  } }t          | |j        |          |f||<   $t          ||           |                    ||j                  |fS )z<Compute square-free decomposition of ``f`` in ``GF(p)[x]``. all)r   rV   r(   rT   	enumerater8   convert)r5   rG   r   f_origcoefffactorsrK   r0   s           r1   dup_gf_sqf_listr     s    FAq!%  A AE15c:::NE7w'' 3 3	6Aq!!QUA..2

vw'''99UAE""G++r3   c                      t          d          )z<Compute square-free decomposition of ``f`` in ``GF(p)[X]``. ry   rz   )r5   rB   rG   r   s       r1   dmp_gf_sqf_listr     r~   r3   c                    |j         rt          | ||          S | }|j        r!t          | |          }t	          | |          } nIt          | |          \  }} |                    t          | |                    rt          | |          } | }t          |           dk    r|g fS g d}}t          | d|          }t          | ||          \  }}	}
	 t          |	d|          }t          |
||          }|s|                    |	|f           nGt          |	||          \  }}	}
|st          |          dk    r|                    ||f           |dz  }t          ||           ||fS )a  
    Return square-free decomposition of a polynomial in ``K[x]``.

    Uses Yun's algorithm from [Yun76]_.

    Examples
    ========

    >>> from sympy.polys import ring, ZZ
    >>> R, x = ring("x", ZZ)

    >>> f = 2*x**5 + 16*x**4 + 50*x**3 + 76*x**2 + 56*x + 16

    >>> R.dup_sqf_list(f)
    (2, [(x + 1, 2), (x + 2, 3)])
    >>> R.dup_sqf_list(f, all=True)
    (2, [(1, 1), (x + 1, 2), (x + 2, 3)])

    See Also
    ========

    dmp_sqf_list:
        Corresponding function for multivariate polynomials.
    sympy.polys.polytools.sqf_list:
        High-level function for square-free factorization of expressions.
    sympy.polys.polytools.Poly.sqf_list:
        Analogous method on :class:`~.Poly`.

    References
    ==========

    [Yun76]_
    r   r   r:   )r   r   r   r   r   r    r   r   r   r   r"   r   appendr8   )r5   rG   r   r   r   r6   rK   rZ   rY   pqrh   s               r1   dup_sqf_listr     s   D 	 .q!----Fz q!aOO A&&q==1&& 	1AFE!}}byAAFAqAAq!$$GAq!Q1Aq! 	MM1a&!!!1a((1a 	"*Q--!##MM1a&!!!	Q vv&&&&=r3   c                     t          | ||          \  }}|r?|d         d         dk    r-t          |d         d         ||          }|dfg|dd         z   S t          |g          }|dfg|z   S )a  
    Return square-free decomposition of a polynomial in ``K[x]``.

    Examples
    ========

    >>> from sympy.polys import ring, ZZ
    >>> R, x = ring("x", ZZ)

    >>> f = 2*x**5 + 16*x**4 + 50*x**3 + 76*x**2 + 56*x + 16

    >>> R.dup_sqf_list_include(f)
    [(2, 1), (x + 1, 2), (x + 2, 3)]
    >>> R.dup_sqf_list_include(f, all=True)
    [(2, 1), (x + 1, 2), (x + 2, 3)]

    r   r   r:   N)r   r   r   )r5   rG   r   r   r   rY   s         r1   dup_sqf_list_includer   A  s    $ "!QC000NE7 "71:a=A%%71:a=%33Ax'!""+%%ugAx'!!r3   c                    |st          | ||          S |j        rt          | |||          S | }|j        r#t	          | ||          }t          | ||          } nLt          | ||          \  }} |                    t	          | ||                    rt          | ||          } | }t          | |          }|dk     r|g fS t          | ||          \  }} i |dk    rt          | d||          }t          | |||          \  }	}
}d}	 t          |
d||          }t          ||||          }t          ||          r|
|<   n7t          |
|||          \  }	}
}|st          |	|          dk    r|	|<   |dz  }qt          ||dz
  ||          \  }}||z  }|D ]-\  }}|g}|v rt!          |         |||          |<   (||<   .fdt#                    D             t%          ||           |fS )a1  
    Return square-free decomposition of a polynomial in `K[X]`.

    Examples
    ========

    >>> from sympy.polys import ring, ZZ
    >>> R, x,y = ring("x,y", ZZ)

    >>> f = x**5 + 2*x**4*y + x**3*y**2

    >>> R.dmp_sqf_list(f)
    (1, [(x + y, 2), (x, 3)])
    >>> R.dmp_sqf_list(f, all=True)
    (1, [(1, 1), (x + y, 2), (x, 3)])

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

    Uses Yun's algorithm for univariate polynomials from [Yun76]_ recrusively.
    The multivariate polynomial is treated as a univariate polynomial in its
    leading variable. Then Yun's algorithm computes the square-free
    factorization of the primitive and the content is factored recursively.

    It would be better to use a dedicated algorithm for multivariate
    polynomials instead.

    See Also
    ========

    dup_sqf_list:
        Corresponding function for univariate polynomials.
    sympy.polys.polytools.sqf_list:
        High-level function for square-free factorization of expressions.
    sympy.polys.polytools.Poly.sqf_list:
        Analogous method on :class:`~.Poly`.
    r   r   r:   Tc                 $    g | ]}|         |fS r<   r<   )r.   rK   r6   s     r1   r?   z dmp_sqf_list.<locals>.<listcomp>  s!    555vay!n555r3   )r   r   r   r   r   r   r!   r   r   r   r'   r   r#   r   r   dmp_sqf_listr   rd   rE   )r5   rB   rG   r   r   r   r7   contentrZ   rY   r   r   rK   rh   coeff_contentresult_contentr/   r6   s                    @r1   r   r   ]  s   L  +Aqc**** 1q!QC0000Fz aA&&Q1%%'1a00q==q!Q//00 	1a  AFE
Q

C
Qwwby q!Q''JGQF
axxQ1a  1a++1a	Aq!$$A1a##A!Q q	#Aq!Q//GAq! jA&&**q	FA	 %1!A#qc$J$J$J!M>	]E !  Qe;;q	3155F1IIF1II5555fVnn555Fvq&)))&=r3   c                 
   |st          | ||          S t          | |||          \  }}|r@|d         d         dk    r.t          |d         d         |||          }|dfg|dd         z   S t          ||          }|dfg|z   S )ah  
    Return square-free decomposition of a polynomial in ``K[x]``.

    Examples
    ========

    >>> from sympy.polys import ring, ZZ
    >>> R, x,y = ring("x,y", ZZ)

    >>> f = x**5 + 2*x**4*y + x**3*y**2

    >>> R.dmp_sqf_list_include(f)
    [(1, 1), (x + y, 2), (x, 3)]
    >>> R.dmp_sqf_list_include(f, all=True)
    [(1, 1), (x + y, 2), (x, 3)]

    r   r   r:   N)r   r   r   r   )r5   rB   rG   r   r   r   rY   s          r1   dmp_sqf_list_includer     s    $  3#Aqc2222!!Qs333NE7 "71:a=A%%71:a=%A66Ax'!""+%%ua  Ax'!!r3   c           
         | st          d          t          | |          } t          |           sg S t          | t	          | |j        |          |          }t          ||          }t          |          D ]<\  }\  }}t          |t	          | ||           |          |          }||dz   f||<   =t          | ||          } t          |           s|S | dfg|z   S )z
    Compute greatest factorial factorization of ``f`` in ``K[x]``.

    Examples
    ========

    >>> from sympy.polys import ring, ZZ
    >>> R, x = ring("x", ZZ)

    >>> R.dup_gff_list(x**5 + 2*x**4 - x**3 - 2*x**2)
    [(x, 1), (x + 2, 4)]

    zDgreatest factorial factorization doesn't exist for a zero polynomialr:   )

ValueErrorr   r   r$   r   onedup_gff_listr   r   r	   )r5   rG   rY   HrK   rZ   r0   s          r1   r   r     s      a_```!QAa==  	AyAE1--q11A"1 	 	IAv19Q1q11155Aq1u:AaDDAq!!}} 	 HF8a<r3   c                 D    |st          | |          S t          |           )z
    Compute greatest factorial factorization of ``f`` in ``K[X]``.

    Examples
    ========

    >>> from sympy.polys import ring, ZZ
    >>> R, x,y = ring("x,y", ZZ)

    )r   r*   r|   s      r1   dmp_gff_listr     s*      -Aq!!!)!,,,r3   N)F)D__doc__sympy.polys.densearithr   r   r   r   r   r   r	   r
   r   r   sympy.polys.densebasicr   r   r   r   r   r   r   r   r   r   r   r   sympy.polys.densetoolsr   r   r   r   r   r   r   r    r!   sympy.polys.euclidtoolsr"   r#   r$   r%   r&   r'   sympy.polys.galoistoolsr(   r)   sympy.polys.polyerrorsr*   r+   r8   rE   rH   rN   r]   rq   rs   ru   rw   r}   r   r   r   r   r   r   r   r   r   r   r<   r3   r1   <module>r      s   > >$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $                           ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) )
" " " " " " " " " " " " " " " "              
     0 0 0@ @ @,  DO O Od% % %PS S SlN- N- N-b$ $ $M M M
!( !( !(H"2 "2 "2J, , , , M M M M
J J J JZ" " " "8i i i iX" " " ">"  "  " J- - - - -r3   