Ë
    7^(h{¹  ã                   ó
  — d dl mZ d dlmZ d dlmZ d dlmZmZm	Z	m
Z
 d dlmZmZ d dlmZ d dlmZmZmZ d dlmZmZ d d	lmZ 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$m%Z% d dl&m'Z' d dl(m)Z) d„ Z*d„ Z+ G d„ de"«      Z,y)é    )ÚRational)ÚS)Úis_eq)Ú	conjugateÚimÚreÚsign)ÚexpÚlog)Úsqrt)ÚacosÚasinÚatan2)ÚcosÚsin)Útrigsimp©Ú	integrate)ÚMutableDenseMatrix)ÚsympifyÚ_sympify)ÚExpr)Ú	fuzzy_notÚfuzzy_or)Úas_int)Úprec_to_dpsc                 óØ   — |�h|j                   r[|j                  du rt        d«      ‚t        d„ | D «       «      }|r-t	        |dz  t        d„ | D «       «      «      du rt        d«      ‚yyyy)z$validate if input norm is consistentNFzInput norm must be positive.c              3   óT   K  — | ]   }|j                   xr |j                  d u –— Œ" y­w)TN)Ú	is_numberÚis_real©Ú.0Úis     úW/var/www/skyplay_api_hub/venv/lib/python3.12/site-packages/sympy/algebras/quaternion.pyú	<genexpr>z_check_norm.<locals>.<genexpr>   s%   è ø€ ÒL¸a˜Ÿ™Ò9¨¯	©	°TÐ(9Ó9ÑLùs   ‚&(é   c              3   ó&   K  — | ]	  }|d z  –— Œ y­w)r&   N© r!   s     r$   r%   z_check_norm.<locals>.<genexpr>   s   è ø€ Ò+C°Q¨A¨q­DÑ+Cùs   ‚zIncompatible value for norm.)r   Úis_positiveÚ
ValueErrorÚallr   Úsum)ÚelementsÚnormÚ	numericals      r$   Ú_check_normr0      st   € àÐ˜DŸNšNØ×Ñ˜uÑ$ÜÐ;Ó<Ð<äÑLÀ8ÔLÓLˆ	Ùœ˜t Q™w¬Ñ+C¸(Ô+CÓ(CÓDÈÑMÜÐ;Ó<Ð<ð Nˆ9ð +Ðó    c                 óÄ  — t        | «      t        k7  rt        d«      ‚t        | «      dk7  rt        dj	                  | «      «      ‚| j                  «       }| j                  «       }|s|st        d«      ‚| j                  «       \  }}}||k(  s||k(  rt        d«      ‚t        | «      t        d«      z
  }|r)t        dj	                  dj                  |«      «      «      ‚|S )	zGvalidate seq and return True if seq is lowercase and False if uppercasezExpected seq to be a string.é   zExpected 3 axes, got `{}`.zkseq must either be fully uppercase (for extrinsic rotations), or fully lowercase, for intrinsic rotations).z"Consecutive axes must be differentÚxyzXYZzNExpected axes from `seq` to be from ['x', 'y', 'z'] or ['X', 'Y', 'Z'], got {}Ú )
ÚtypeÚstrr*   ÚlenÚformatÚisupperÚislowerÚlowerÚsetÚjoin)ÚseqÚ	intrinsicÚ	extrinsicr#   ÚjÚkÚbads          r$   Ú_is_extrinsicrE      sÖ   € äˆCƒy”CÒÜÐ7Ó8Ð8Ü
ˆ3ƒx�1‚}ÜÐ5×<Ñ<¸SÓAÓBÐBà—‘“€IØ—‘“€IÙ™Üð 'ó (ð 	(ð �i‰i‹k�G€A€qˆ!Ø	ˆQŠ�A˜’FÜÐ=Ó>Ð>ä
ˆc‹(”S˜“]Ñ
"€CÙ
Üð "ç"(¡&¨¯©°«Ó"6ó8ð 	8ð Ðr1   c                   ó  ‡ — e Zd ZdZdZdZd;ˆ fd„	Zd„ Zed„ «       Z	ed„ «       Z
ed„ «       Zed	„ «       Zed
„ «       Zed„ «       Zed„ «       Zd<d„Zed„ «       Zed„ «       Zd=d„Zed„ «       Zed„ «       Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Z d„ Z!d„ Z"d„ Z#e$d „ «       Z%d!„ Z&d"„ Z'd#„ Z(d$„ Z)d%„ Z*d&„ Z+d'„ Z,d(„ Z-d)„ Z.d*„ Z/d+„ Z0e$d,„ «       Z1d-„ Z2d>d.„Z3d/„ Z4d0„ Z5d1„ Z6d2„ Z7d3„ Z8d4„ Z9d5„ Z:ed6„ «       Z;d7„ Z<d8„ Z=d9„ Z>d:„ Z?ˆ xZ@S )?Ú
Quaternionaö  Provides basic quaternion operations.
    Quaternion objects can be instantiated as ``Quaternion(a, b, c, d)``
    as in $q = a + bi + cj + dk$.

    Parameters
    ==========

    norm : None or number
        Pre-defined quaternion norm. If a value is given, Quaternion.norm
        returns this pre-defined value instead of calculating the norm

    Examples
    ========

    >>> from sympy import Quaternion
    >>> q = Quaternion(1, 2, 3, 4)
    >>> q
    1 + 2*i + 3*j + 4*k

    Quaternions over complex fields can be defined as:

    >>> from sympy import Quaternion
    >>> from sympy import symbols, I
    >>> x = symbols('x')
    >>> q1 = Quaternion(x, x**3, x, x**2, real_field = False)
    >>> q2 = Quaternion(3 + 4*I, 2 + 5*I, 0, 7 + 8*I, real_field = False)
    >>> q1
    x + x**3*i + x*j + x**2*k
    >>> q2
    (3 + 4*I) + (2 + 5*I)*i + 0*j + (7 + 8*I)*k

    Defining symbolic unit quaternions:

    >>> from sympy import Quaternion
    >>> from sympy.abc import w, x, y, z
    >>> q = Quaternion(w, x, y, z, norm=1)
    >>> q
    w + x*i + y*j + z*k
    >>> q.norm()
    1

    References
    ==========

    .. [1] https://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/
    .. [2] https://en.wikipedia.org/wiki/Quaternion

    g      &@Fc                 óÒ   •— t        t        ||||f«      \  }}}}t        d„ ||||fD «       «      rt        d«      ‚t        ‰| �  | ||||«      }||_        |j                  |«       |S )Nc              3   ó8   K  — | ]  }|j                   d u –— Œ y­w)FN)Úis_commutativer!   s     r$   r%   z%Quaternion.__new__.<locals>.<genexpr>r   s   è ø€ Ò?¨Qˆq×Ñ 5Ô(Ñ?ùs   ‚z arguments have to be commutative)Úmapr   Úanyr*   ÚsuperÚ__new__Ú_real_fieldÚset_norm)	ÚclsÚaÚbÚcÚdÚ
real_fieldr.   ÚobjÚ	__class__s	           €r$   rN   zQuaternion.__new__o   so   ø€ Üœ 1 a¨¨A ,Ó/‰
ˆˆ1ˆa�äÑ?°1°a¸¸A°,Ô?Ô?ÜÐ?Ó@Ð@Ü‰g‰o˜c 1 a¨¨AÓ.ˆØ$ˆŒØ�‰�TÔØˆ
r1   c                 óT   — t        |«      }t        | j                  |«       || _        y)aÃ  Sets norm of an already instantiated quaternion.

        Parameters
        ==========

        norm : None or number
            Pre-defined quaternion norm. If a value is given, Quaternion.norm
            returns this pre-defined value instead of calculating the norm

        Examples
        ========

        >>> from sympy import Quaternion
        >>> from sympy.abc import a, b, c, d
        >>> q = Quaternion(a, b, c, d)
        >>> q.norm()
        sqrt(a**2 + b**2 + c**2 + d**2)

        Setting the norm:

        >>> q.set_norm(1)
        >>> q.norm()
        1

        Removing set norm:

        >>> q.set_norm(None)
        >>> q.norm()
        sqrt(a**2 + b**2 + c**2 + d**2)

        N)r   r0   ÚargsÚ_norm)Úselfr.   s     r$   rP   zQuaternion.set_normy   s#   € ô@ �t‹}ˆÜ�D—I‘I˜tÔ$Øˆ�
r1   c                 ó    — | j                   d   S )Nr   ©rZ   ©r\   s    r$   rR   zQuaternion.a�   ó   € à�y‰y˜‰|Ðr1   c                 ó    — | j                   d   S )Né   r^   r_   s    r$   rS   zQuaternion.b¡   r`   r1   c                 ó    — | j                   d   S )Nr&   r^   r_   s    r$   rT   zQuaternion.c¥   r`   r1   c                 ó    — | j                   d   S )Nr3   r^   r_   s    r$   rU   zQuaternion.d©   r`   r1   c                 ó   — | j                   S ©N)rO   r_   s    r$   rV   zQuaternion.real_field­   s   € à×ÑÐr1   c           	      óŒ  — t        | j                  | j                   | j                   | j                   g| j                  | j                  | j                   | j                  g| j                  | j                  | j                  | j                   g| j                  | j                   | j                  | j                  gg«      S )aœ  Returns 4 x 4 Matrix equivalent to a Hamilton product from the
        left. This can be useful when treating quaternion elements as column
        vectors. Given a quaternion $q = a + bi + cj + dk$ where a, b, c and d
        are real numbers, the product matrix from the left is:

        .. math::

            M  =  \begin{bmatrix} a  &-b  &-c  &-d \\
                                  b  & a  &-d  & c \\
                                  c  & d  & a  &-b \\
                                  d  &-c  & b  & a \end{bmatrix}

        Examples
        ========

        >>> from sympy import Quaternion
        >>> from sympy.abc import a, b, c, d
        >>> q1 = Quaternion(1, 0, 0, 1)
        >>> q2 = Quaternion(a, b, c, d)
        >>> q1.product_matrix_left
        Matrix([
        [1, 0,  0, -1],
        [0, 1, -1,  0],
        [0, 1,  1,  0],
        [1, 0,  0,  1]])

        >>> q1.product_matrix_left * q2.to_Matrix()
        Matrix([
        [a - d],
        [b - c],
        [b + c],
        [a + d]])

        This is equivalent to:

        >>> (q1 * q2).to_Matrix()
        Matrix([
        [a - d],
        [b - c],
        [b + c],
        [a + d]])
        ©ÚMatrixrR   rS   rT   rU   r_   s    r$   Úproduct_matrix_leftzQuaternion.product_matrix_left±   s“   € ôX Ø—‘˜$Ÿ&™&˜ 4§6¡6 '¨D¯F©F¨7Ð3Ø—‘˜Ÿ™ $§&¡& ¨$¯&©&Ð1Ø—‘˜Ÿ™ §¡¨$¯&©&¨Ð1Ø—‘˜$Ÿ&™&˜ $§&¡&¨$¯&©&Ð1ð	3ó 4ð 	4r1   c           	      óŒ  — t        | j                  | j                   | j                   | j                   g| j                  | j                  | j                  | j                   g| j                  | j                   | j                  | j                  g| j                  | j                  | j                   | j                  gg«      S )aM  Returns 4 x 4 Matrix equivalent to a Hamilton product from the
        right. This can be useful when treating quaternion elements as column
        vectors. Given a quaternion $q = a + bi + cj + dk$ where a, b, c and d
        are real numbers, the product matrix from the left is:

        .. math::

            M  =  \begin{bmatrix} a  &-b  &-c  &-d \\
                                  b  & a  & d  &-c \\
                                  c  &-d  & a  & b \\
                                  d  & c  &-b  & a \end{bmatrix}


        Examples
        ========

        >>> from sympy import Quaternion
        >>> from sympy.abc import a, b, c, d
        >>> q1 = Quaternion(a, b, c, d)
        >>> q2 = Quaternion(1, 0, 0, 1)
        >>> q2.product_matrix_right
        Matrix([
        [1, 0, 0, -1],
        [0, 1, 1, 0],
        [0, -1, 1, 0],
        [1, 0, 0, 1]])

        Note the switched arguments: the matrix represents the quaternion on
        the right, but is still considered as a matrix multiplication from the
        left.

        >>> q2.product_matrix_right * q1.to_Matrix()
        Matrix([
        [ a - d],
        [ b + c],
        [-b + c],
        [ a + d]])

        This is equivalent to:

        >>> (q1 * q2).to_Matrix()
        Matrix([
        [ a - d],
        [ b + c],
        [-b + c],
        [ a + d]])
        rh   r_   s    r$   Úproduct_matrix_rightzQuaternion.product_matrix_rightã   s“   € ôb Ø—‘˜$Ÿ&™&˜ 4§6¡6 '¨D¯F©F¨7Ð3Ø—‘˜Ÿ™ §¡¨$¯&©&¨Ð1Ø—‘˜$Ÿ&™&˜ $§&¡&¨$¯&©&Ð1Ø—‘˜Ÿ™ $§&¡& ¨$¯&©&Ð1ð	3ó 4ð 	4r1   c                 ó`   — |rt        | j                  dd «      S t        | j                  «      S )a³  Returns elements of quaternion as a column vector.
        By default, a ``Matrix`` of length 4 is returned, with the real part as the
        first element.
        If ``vector_only`` is ``True``, returns only imaginary part as a Matrix of
        length 3.

        Parameters
        ==========

        vector_only : bool
            If True, only imaginary part is returned.
            Default value: False

        Returns
        =======

        Matrix
            A column vector constructed by the elements of the quaternion.

        Examples
        ========

        >>> from sympy import Quaternion
        >>> from sympy.abc import a, b, c, d
        >>> q = Quaternion(a, b, c, d)
        >>> q
        a + b*i + c*j + d*k

        >>> q.to_Matrix()
        Matrix([
        [a],
        [b],
        [c],
        [d]])


        >>> q.to_Matrix(vector_only=True)
        Matrix([
        [b],
        [c],
        [d]])

        rb   N)ri   rZ   )r\   Úvector_onlys     r$   Ú	to_MatrixzQuaternion.to_Matrix  s,   € ñX Ü˜$Ÿ)™) A B˜-Ó(Ð(ä˜$Ÿ)™)Ó$Ð$r1   c                 ó’   — t        |«      }|dk7  r|dk7  rt        dj                  |«      «      ‚|dk(  rt        dg|¢­Ž S t        |Ž S )aû  Returns quaternion from elements of a column vector`.
        If vector_only is True, returns only imaginary part as a Matrix of
        length 3.

        Parameters
        ==========

        elements : Matrix, list or tuple of length 3 or 4. If length is 3,
            assume real part is zero.
            Default value: False

        Returns
        =======

        Quaternion
            A quaternion created from the input elements.

        Examples
        ========

        >>> from sympy import Quaternion
        >>> from sympy.abc import a, b, c, d
        >>> q = Quaternion.from_Matrix([a, b, c, d])
        >>> q
        a + b*i + c*j + d*k

        >>> q = Quaternion.from_Matrix([b, c, d])
        >>> q
        0 + b*i + c*j + d*k

        r3   é   z7Input elements must have length 3 or 4, got {} elementsr   )r8   r*   r9   rG   )rQ   r-   Úlengths      r$   Úfrom_MatrixzQuaternion.from_MatrixK  sZ   € ôB �X“ˆØ�QŠ;˜6 Qš;Üð (ß(.©¨v«ó8ð 8ð �QŠ;Ü˜aÐ+ (Ò+Ð+ä˜xÐ(Ð(r1   c                 óÚ  — t        |«      dk7  rt        d«      ‚t        |«      }|j                  «       \  }}}dD �cg c]  }||k(  rdnd‘Œ }}dD �cg c]  }||k(  rdnd‘Œ }	}dD �cg c]  }||k(  rdnd‘Œ }
}| j	                  ||d   «      }| j	                  |	|d   «      }| j	                  |
|d   «      }|rt        ||z  |z  «      S t        ||z  |z  «      S c c}w c c}w c c}w )aâ  Returns quaternion equivalent to rotation represented by the Euler
        angles, in the sequence defined by ``seq``.

        Parameters
        ==========

        angles : list, tuple or Matrix of 3 numbers
            The Euler angles (in radians).
        seq : string of length 3
            Represents the sequence of rotations.
            For extrinsic rotations, seq must be all lowercase and its elements
            must be from the set ``{'x', 'y', 'z'}``
            For intrinsic rotations, seq must be all uppercase and its elements
            must be from the set ``{'X', 'Y', 'Z'}``

        Returns
        =======

        Quaternion
            The normalized rotation quaternion calculated from the Euler angles
            in the given sequence.

        Examples
        ========

        >>> from sympy import Quaternion
        >>> from sympy import pi
        >>> q = Quaternion.from_euler([pi/2, 0, 0], 'xyz')
        >>> q
        sqrt(2)/2 + sqrt(2)/2*i + 0*j + 0*k

        >>> q = Quaternion.from_euler([0, pi/2, pi] , 'zyz')
        >>> q
        0 + (-sqrt(2)/2)*i + 0*j + sqrt(2)/2*k

        >>> q = Quaternion.from_euler([0, pi/2, pi] , 'ZYZ')
        >>> q
        0 + sqrt(2)/2*i + 0*j + sqrt(2)/2*k

        r3   z3 angles must be given.Úxyzrb   r   r&   )r8   r*   rE   r<   Úfrom_axis_angler   )rQ   Úanglesr?   rA   r#   rB   rC   ÚnÚeiÚejÚekÚqiÚqjÚqks                 r$   Ú
from_eulerzQuaternion.from_eulerv  s  € ôV ˆv‹;˜!ÒÜÐ6Ó7Ð7ä! #Ó&ˆ	Ø—)‘)“+‰ˆˆ1ˆað +0Ö0 Q�1˜’6‰a˜qÑ Ð0ˆÐ0Ø*/Ö0 Q�1˜’6‰a˜qÑ Ð0ˆÐ0Ø*/Ö0 Q�1˜’6‰a˜qÑ Ð0ˆÐ0ð × Ñ   V¨A¡YÓ/ˆØ× Ñ   V¨A¡YÓ/ˆØ× Ñ   V¨A¡YÓ/ˆáÜ˜B ™G b™LÓ)Ð)ä˜B ™G b™LÓ)Ð)ùò 1ùÚ0ùÚ0s   ½CÁC#Á)C(c           	      ó˜  — | j                  «       rt        d«      ‚g d¢}t        |«      }|j                  «       \  }}}dj	                  |«      dz   }dj	                  |«      dz   }dj	                  |«      dz   }|s||}}||k(  }	|	rd|z
  |z
  }||z
  ||z
  z  ||z
  z  dz  }
| j
                  | j                  | j                  | j                  g}|d   }||   }||   }||   |
z  }|	s||z
  ||z   ||z   ||z
  f\  }}}}|ry|	r:| j                  «       dz  }t        ||z  ||z  z   ||z  z
  ||z  z
  |z  «      |d<   n“d| j                  «       dz  z  }t        ||z  ||z  z   ||z  z
  ||z  z
  |z  «      |d<   nVdt        t        ||z  ||z  z   «      t        ||z  ||z  z   «      «      z  |d<   |	s|dxx   t        j                  dz  z  cc<   d}t!        |t        j"                  «      rt!        |t        j"                  «      rd}t!        |t        j"                  «      rt!        |t        j"                  «      rd}|dk(  r~|r9t        ||«      t        ||«      z   |d<   t        ||«      t        ||«      z
  |d<   nžt        ||z  ||z  z   ||z  ||z  z
  «      |d<   t        ||z  ||z  z
  ||z  ||z  z   «      |d<   n[t        j"                  |d| z  <   |dk(  rdt        ||«      z  |d|z  <   n)dt        ||«      z  |d|z  <   |d|z  xx   |rdndz  cc<   |	s|dxx   |
z  cc<   |rt%        |d	d	d…   «      S t%        |«      S )
a}  Returns Euler angles representing same rotation as the quaternion,
        in the sequence given by ``seq``. This implements the method described
        in [1]_.

        For degenerate cases (gymbal lock cases), the third angle is
        set to zero.

        Parameters
        ==========

        seq : string of length 3
            Represents the sequence of rotations.
            For extrinsic rotations, seq must be all lowercase and its elements
            must be from the set ``{'x', 'y', 'z'}``
            For intrinsic rotations, seq must be all uppercase and its elements
            must be from the set ``{'X', 'Y', 'Z'}``

        angle_addition : bool
            When True, first and third angles are given as an addition and
            subtraction of two simpler ``atan2`` expressions. When False, the
            first and third angles are each given by a single more complicated
            ``atan2`` expression. This equivalent expression is given by:

            .. math::

                \operatorname{atan_2} (b,a) \pm \operatorname{atan_2} (d,c) =
                \operatorname{atan_2} (bc\pm ad, ac\mp bd)

            Default value: True

        avoid_square_root : bool
            When True, the second angle is calculated with an expression based
            on ``acos``, which is slightly more complicated but avoids a square
            root. When False, second angle is calculated with ``atan2``, which
            is simpler and can be better for numerical reasons (some
            numerical implementations of ``acos`` have problems near zero).
            Default value: False


        Returns
        =======

        Tuple
            The Euler angles calculated from the quaternion

        Examples
        ========

        >>> from sympy import Quaternion
        >>> from sympy.abc import a, b, c, d
        >>> euler = Quaternion(a, b, c, d).to_euler('zyz')
        >>> euler
        (-atan2(-b, c) + atan2(d, a),
         2*atan2(sqrt(b**2 + c**2), sqrt(a**2 + d**2)),
         atan2(-b, c) + atan2(d, a))


        References
        ==========

        .. [1] https://doi.org/10.1371/journal.pone.0276302

        z(Cannot convert a quaternion with norm 0.)r   r   r   ru   rb   é   r&   r   éÿÿÿÿN)Úis_zero_quaternionr*   rE   r<   ÚindexrR   rS   rT   rU   r.   r   r   r   r   r   ÚPir   ÚZeroÚtuple)r\   r?   Úangle_additionÚavoid_square_rootrw   rA   r#   rB   rC   Ú	symmetricr	   r-   rR   rS   rT   rU   Ún2Úcases                     r$   Úto_eulerzQuaternion.to_euler¶  sy  € ð@ ×"Ñ"Ô$ÜÐGÓHÐHâˆä! #Ó&ˆ	Ø—)‘)“+‰ˆˆ1ˆað �K‰K˜‹N˜QÑˆØ�K‰K˜‹N˜QÑˆØ�K‰K˜‹N˜QÑˆáØ�aˆqˆAð ˜‘Fˆ	ÙØ�A‘˜‘	ˆAð �A‘˜!˜a™%Ñ  A¨¡EÑ*¨aÑ/ˆð —F‘F˜DŸF™F D§F¡F¨D¯F©FÐ3ˆØ�Q‰KˆØ�Q‰KˆØ�Q‰KˆØ�Q‰K˜$ÑˆáØ˜Q™  A¡ q¨1¡u¨a°!©eÐ3‰JˆAˆq�!�QáÙØ—Y‘Y“[ !‘^�Ü  ! a¡%¨!¨a©%¡-°!°a±%Ñ"7¸!¸a¹%Ñ"?À2Ñ!EÓF��q’	à˜Ÿ™› a™Ñ'�Ü  ! a¡%¨!¨a©%¡-°!°a±%Ñ"7¸!¸a¹%Ñ"?À2Ñ!EÓF��q’	àœE¤$ q¨1¡u¨q°1©u¡}Ó"5´t¸AÀ¹EÀAÈÁE¹MÓ7JÓKÑKˆF�1‰IÙØ�q“	œQŸT™T A™XÑ%“	ð ˆÜ�”A—F‘FÔ¤ a¬¯©Ô 0ØˆDÜ�”A—F‘FÔ¤ a¬¯©Ô 0ØˆDà�1Š9ÙÜ! ! Q›K¬%°°1«+Ñ5��q‘	Ü! ! Q›K¬%°°1«+Ñ5��q’	ä! ! A¡#¨¨!©¡)¨Q¨q©S°1°Q±3©YÓ7��q‘	Ü! ! A¡#¨¨!©¡)¨Q¨q©S°1°Q±3©YÓ7��q’	ô +,¯&©&ˆF�1˜I˜Ñ&Ñ'Ø�qŠyØ()¬E°!°Q«K©��q˜9‘}Ò%à()¬E°!°Q«K©��q˜9‘}Ñ%Ø�q˜9‘}Ó%±	©"¸qÑAÓ%ñ Ø�1‹I˜Ñ‹IáÜ˜¡ " ™Ó&Ð&ä˜“=Ð r1   c                 ó  — |\  }}}t        |dz  |dz  z   |dz  z   «      }||z  ||z  ||z  }}}t        |t        j                  z  «      }t	        |t        j                  z  «      }||z  }	||z  }
||z  } | ||	|
|«      S )aÈ  Returns a rotation quaternion given the axis and the angle of rotation.

        Parameters
        ==========

        vector : tuple of three numbers
            The vector representation of the given axis.
        angle : number
            The angle by which axis is rotated (in radians).

        Returns
        =======

        Quaternion
            The normalized rotation quaternion calculated from the given axis and the angle of rotation.

        Examples
        ========

        >>> from sympy import Quaternion
        >>> from sympy import pi, sqrt
        >>> q = Quaternion.from_axis_angle((sqrt(3)/3, sqrt(3)/3, sqrt(3)/3), 2*pi/3)
        >>> q
        1/2 + 1/2*i + 1/2*j + 1/2*k

        r&   )r   r   r   ÚHalfr   )rQ   ÚvectorÚangleÚxÚyÚzr.   ÚsrR   rS   rT   rU   s               r$   rv   zQuaternion.from_axis_angleD  s˜   € ð8 ‰	ˆˆAˆqÜ�A�q‘D˜1˜a™4‘K ! Q¡$Ñ&Ó'ˆØ˜‘X˜q 4™x¨¨T©ˆqˆAˆÜ�œŸ™‘ÓˆÜ�œŸ™‘ÓˆØ�‰EˆØ�‰EˆØ�‰Eˆñ �1�a˜˜A‹Ðr1   c                 óâ  — |j                  «       t        dd«      z  }t        ||d   z   |d   z   |d   z   «      dz  }t        ||d   z   |d   z
  |d   z
  «      dz  }t        ||d   z
  |d   z   |d   z
  «      dz  }t        ||d   z
  |d   z
  |d   z   «      dz  }|t        |d   |d   z
  «      z  }|t        |d	   |d
   z
  «      z  }|t        |d   |d   z
  «      z  }t	        ||||«      S )a—  Returns the equivalent quaternion of a matrix. The quaternion will be normalized
        only if the matrix is special orthogonal (orthogonal and det(M) = 1).

        Parameters
        ==========

        M : Matrix
            Input matrix to be converted to equivalent quaternion. M must be special
            orthogonal (orthogonal and det(M) = 1) for the quaternion to be normalized.

        Returns
        =======

        Quaternion
            The quaternion equivalent to given matrix.

        Examples
        ========

        >>> from sympy import Quaternion
        >>> from sympy import Matrix, symbols, cos, sin, trigsimp
        >>> x = symbols('x')
        >>> M = Matrix([[cos(x), -sin(x), 0], [sin(x), cos(x), 0], [0, 0, 1]])
        >>> q = trigsimp(Quaternion.from_rotation_matrix(M))
        >>> q
        sqrt(2)*sqrt(cos(x) + 1)/2 + 0*i + 0*j + sqrt(2 - 2*cos(x))*sign(sin(x))/2*k

        rb   r3   )r   r   )rb   rb   )r&   r&   r&   )r&   rb   )rb   r&   )r   r&   )r&   r   )rb   r   )r   rb   )Údetr   r   r	   rG   )rQ   ÚMÚabsQrR   rS   rT   rU   s          r$   Úfrom_rotation_matrixzQuaternion.from_rotation_matrixo  s#  € ð> �u‰u‹wœ  A›Ñ&ˆä�˜˜$™‘ ! D¡'Ñ)¨A¨d©GÑ3Ó4°qÑ8ˆÜ�˜˜$™‘ ! D¡'Ñ)¨A¨d©GÑ3Ó4°qÑ8ˆÜ�˜˜$™‘ ! D¡'Ñ)¨A¨d©GÑ3Ó4°qÑ8ˆÜ�˜˜$™‘ ! D¡'Ñ)¨A¨d©GÑ3Ó4°qÑ8ˆà”�Q�t‘W˜q ™wÑ&Ó'Ñ'ˆØ”�Q�t‘W˜q ™wÑ&Ó'Ñ'ˆØ”�Q�t‘W˜q ™wÑ&Ó'Ñ'ˆä˜!˜Q  1Ó%Ð%r1   c                 ó$   — | j                  |«      S rf   ©Úadd©r\   Úothers     r$   Ú__add__zQuaternion.__add__›  ó   € Ø�x‰x˜‹Ðr1   c                 ó$   — | j                  |«      S rf   rœ   rž   s     r$   Ú__radd__zQuaternion.__radd__ž  r¡   r1   c                 ó*   — | j                  |dz  «      S ©Nr‚   rœ   rž   s     r$   Ú__sub__zQuaternion.__sub__¡  s   € Ø�x‰x˜˜b™Ó!Ð!r1   c                 ó8   — | j                  | t        |«      «      S rf   ©Ú_generic_mulr   rž   s     r$   Ú__mul__zQuaternion.__mul__¤  s   € Ø× Ñ  ¤x°£Ó7Ð7r1   c                 ó8   — | j                  t        |«      | «      S rf   r¨   rž   s     r$   Ú__rmul__zQuaternion.__rmul__§  s   € Ø× Ñ ¤¨%£°$Ó7Ð7r1   c                 ó$   — | j                  |«      S rf   )Úpow)r\   Úps     r$   Ú__pow__zQuaternion.__pow__ª  s   € Ø�x‰x˜‹{Ðr1   c                 óv   — t        | j                   | j                   | j                   | j                   «      S rf   )rG   rR   rS   rT   rU   r_   s    r$   Ú__neg__zQuaternion.__neg__­  s+   € Ü˜4Ÿ6™6˜' D§F¡F 7¨T¯V©V¨G°d·f±f°WÓ=Ð=r1   c                 ó$   — | t        |«      dz  z  S r¥   ©r   rž   s     r$   Ú__truediv__zQuaternion.__truediv__°  s   € Ø”g˜e“n bÑ(Ñ(Ð(r1   c                 ó$   — t        |«      | dz  z  S r¥   r´   rž   s     r$   Ú__rtruediv__zQuaternion.__rtruediv__³  s   € Ü�u‹~  b¡Ñ(Ð(r1   c                 ó    —  | j                   |Ž S rf   r   ©r\   rZ   s     r$   Ú_eval_IntegralzQuaternion._eval_Integral¶  s   € Øˆt�~‰~˜tÐ$Ð$r1   c           
      óž   — |j                  dd«        | j                  | j                  D �cg c]  } |j                  |i |¤Ž‘Œ c}Ž S c c}w )NÚevaluateT)Ú
setdefaultÚfuncrZ   Údiff)r\   ÚsymbolsÚkwargsrR   s       r$   r¿   zQuaternion.diff¹  sE   € Ø×Ñ˜* dÔ+Øˆt�y‰yÀÇ	Á	ÖJ¸!˜6˜1Ÿ6™6 7Ð5¨fÓ5ÒJÐKÐKùÒJs   ­A
c                 ó|  — | }t        |«      }t        |t        «      s¶|j                  rZ|j                  rNt        t        |«      |j                  z   t        |«      |j                  z   |j                  |j                  «      S |j                  r9t        |j                  |z   |j                  |j                  |j                  «      S t        d«      ‚t        |j                  |j                  z   |j                  |j                  z   |j                  |j                  z   |j                  |j                  z   «      S )a¯  Adds quaternions.

        Parameters
        ==========

        other : Quaternion
            The quaternion to add to current (self) quaternion.

        Returns
        =======

        Quaternion
            The resultant quaternion after adding self to other

        Examples
        ========

        >>> from sympy import Quaternion
        >>> from sympy import symbols
        >>> q1 = Quaternion(1, 2, 3, 4)
        >>> q2 = Quaternion(5, 6, 7, 8)
        >>> q1.add(q2)
        6 + 8*i + 10*j + 12*k
        >>> q1 + 5
        6 + 2*i + 3*j + 4*k
        >>> x = symbols('x', real = True)
        >>> q1.add(x)
        (x + 1) + 2*i + 3*j + 4*k

        Quaternions over complex fields :

        >>> from sympy import Quaternion
        >>> from sympy import I
        >>> q3 = Quaternion(3 + 4*I, 2 + 5*I, 0, 7 + 8*I, real_field = False)
        >>> q3.add(2 + 3*I)
        (5 + 7*I) + (2 + 5*I)*i + 0*j + (7 + 8*I)*k

        z<Only commutative expressions can be added with a Quaternion.)r   Ú
isinstancerG   rV   Ú
is_complexr   rR   r   rS   rT   rU   rJ   r*   )r\   rŸ   Úq1Úq2s       r$   r�   zQuaternion.add½  sá   € ðN ˆÜ�U‹^ˆô ˜"œjÔ)Ø�}Š} §¢Ü!¤" R£&¨2¯4©4¡-´°B³¸"¿$¹$±ÀÇÁÀbÇdÁdÓKÐKØ×"Ò"Ü! "§$¡$¨¡)¨R¯T©T°2·4±4¸¿¹Ó>Ð>ä Ð!_Ó`Ð`ä˜"Ÿ$™$ §¡™+ r§t¡t¨b¯d©d¡{°B·D±D¸2¿4¹4±KÀÇÁØŸD™DñB!ó "ð 	"r1   c                 ó8   — | j                  | t        |«      «      S )añ  Multiplies quaternions.

        Parameters
        ==========

        other : Quaternion or symbol
            The quaternion to multiply to current (self) quaternion.

        Returns
        =======

        Quaternion
            The resultant quaternion after multiplying self with other

        Examples
        ========

        >>> from sympy import Quaternion
        >>> from sympy import symbols
        >>> q1 = Quaternion(1, 2, 3, 4)
        >>> q2 = Quaternion(5, 6, 7, 8)
        >>> q1.mul(q2)
        (-60) + 12*i + 30*j + 24*k
        >>> q1.mul(2)
        2 + 4*i + 6*j + 8*k
        >>> x = symbols('x', real = True)
        >>> q1.mul(x)
        x + 2*x*i + 3*x*j + 4*x*k

        Quaternions over complex fields :

        >>> from sympy import Quaternion
        >>> from sympy import I
        >>> q3 = Quaternion(3 + 4*I, 2 + 5*I, 0, 7 + 8*I, real_field = False)
        >>> q3.mul(2 + 3*I)
        (2 + 3*I)*(3 + 4*I) + (2 + 3*I)*(2 + 5*I)*i + 0*j + (2 + 3*I)*(7 + 8*I)*k

        r¨   rž   s     r$   ÚmulzQuaternion.muló  s   € ðN × Ñ  ¤x°£Ó7Ð7r1   c                 ó   — t        | t        «      st        |t        «      s| |z  S t        | t        «      s”|j                  r/| j                  r#t        t	        | «      t        | «      dd«      |z  S | j                  rBt        | |j                  z  | |j                  z  | |j                  z  | |j                  z  «      S t        d«      ‚t        |t        «      s”| j                  r/|j                  r#| t        t	        |«      t        |«      dd«      z  S |j                  rBt        || j                  z  || j                  z  || j                  z  || j                  z  «      S t        d«      ‚| j                  €|j                  €d}n!| j                  «       |j                  «       z  }t        | j                   |j                  z  | j                  |j                  z  z
  | j                  |j                  z  z
  | j                  |j                  z  z   | j                  |j                  z  | j                  |j                  z  z   | j                  |j                  z  z
  | j                  |j                  z  z   | j                   |j                  z  | j                  |j                  z  z   | j                  |j                  z  z   | j                  |j                  z  z   | j                  |j                  z  | j                  |j                  z  z
  | j                  |j                  z  z   | j                  |j                  z  z   |¬«      S )an  Generic multiplication.

        Parameters
        ==========

        q1 : Quaternion or symbol
        q2 : Quaternion or symbol

        It is important to note that if neither q1 nor q2 is a Quaternion,
        this function simply returns q1 * q2.

        Returns
        =======

        Quaternion
            The resultant quaternion after multiplying q1 and q2

        Examples
        ========

        >>> from sympy import Quaternion
        >>> from sympy import Symbol, S
        >>> q1 = Quaternion(1, 2, 3, 4)
        >>> q2 = Quaternion(5, 6, 7, 8)
        >>> Quaternion._generic_mul(q1, q2)
        (-60) + 12*i + 30*j + 24*k
        >>> Quaternion._generic_mul(q1, S(2))
        2 + 4*i + 6*j + 8*k
        >>> x = Symbol('x', real = True)
        >>> Quaternion._generic_mul(q1, x)
        x + 2*x*i + 3*x*j + 4*x*k

        Quaternions over complex fields :

        >>> from sympy import I
        >>> q3 = Quaternion(3 + 4*I, 2 + 5*I, 0, 7 + 8*I, real_field = False)
        >>> Quaternion._generic_mul(q3, 2 + 3*I)
        (2 + 3*I)*(3 + 4*I) + (2 + 3*I)*(2 + 5*I)*i + 0*j + (2 + 3*I)*(7 + 8*I)*k

        r   zAOnly commutative expressions can be multiplied with a Quaternion.N©r.   )rÃ   rG   rV   rÄ   r   r   rJ   rR   rS   rT   rU   r*   r[   r.   )rÅ   rÆ   r.   s      r$   r©   zQuaternion._generic_mul  sf  € ôV ˜"œjÔ)´*¸RÄÔ2LØ˜‘7ˆNô ˜"œjÔ)Ø�}Š} §¢Ü!¤" R£&¬"¨R«&°!°QÓ7¸"Ñ<Ð<Ø×"Ò"Ü! " r§t¡t¡)¨R°"·$±$©Y¸¸R¿T¹T¹	À2ÈÏÉÁ9ÓMÐMä Ð!dÓeÐeô ˜"œjÔ)Ø�}Š} §¢ØœJ¤r¨"£v¬r°"«v°q¸!Ó<Ñ<Ð<Ø×"Ò"Ü! " r§t¡t¡)¨R°"·$±$©Y¸¸R¿T¹T¹	À2ÈÏÉÁ9ÓMÐMä Ð!dÓeÐeð �8‰8Ð §¡Ð 0Ø‰Dà—7‘7“9˜rŸw™w›yÑ(ˆDä˜2Ÿ4™4˜% §¡™* r§t¡t¨B¯D©D¡yÑ0°2·4±4¸¿¹±9Ñ<¸r¿t¹tÀBÇDÁD¹yÑHØŸ$™$˜rŸt™t™) b§d¡d¨2¯4©4¡iÑ/°"·$±$°r·t±t±)Ñ;¸b¿d¹dÀ2Ç4Á4¹iÑGØŸ4™4˜% §¡™* r§t¡t¨B¯D©D¡yÑ0°2·4±4¸¿¹±9Ñ<¸r¿t¹tÀBÇDÁD¹yÑHØŸ$™$˜rŸt™t™) b§d¡d¨2¯4©4¡iÑ/°"·$±$°r·t±t±)Ñ;¸b¿d¹dÀRÇTÁT¹kÑIØ#ô	%ð 	%r1   c                 ó�   — | }t        |j                  |j                   |j                   |j                   |j
                  ¬«      S )z(Returns the conjugate of the quaternion.rÊ   )rG   rR   rS   rT   rU   r[   ©r\   Úqs     r$   Ú_eval_conjugatezQuaternion._eval_conjugateh  s4   € àˆÜ˜!Ÿ#™# §¡˜t a§c¡c T¨A¯C©C¨4°a·g±gÔ>Ð>r1   c                 óØ   — | j                   €S| }t        t        |j                  dz  |j                  dz  z   |j
                  dz  z   |j                  dz  z   «      «      S | j                   S )z#Returns the norm of the quaternion.r&   )r[   r   r   rR   rS   rT   rU   rÌ   s     r$   r.   zQuaternion.normm  s[   € à�:‰:ÐØˆAô œ §¡ a¡¨!¯#©#¨q©&¡°1·3±3¸±6Ñ!9¸A¿C¹CÀ¹FÑ!BÓCÓDÐDà�z‰zÐr1   c                 ó2   — | }|d|j                  «       z  z  S )z.Returns the normalized form of the quaternion.rb   rÊ   rÌ   s     r$   Ú	normalizezQuaternion.normalizew  s   € àˆØ�A�a—f‘f“h‘JÑÐr1   c                 ó€   — | }|j                  «       st        d«      ‚t        |«      d|j                  «       dz  z  z  S )z&Returns the inverse of the quaternion.z6Cannot compute inverse for a quaternion with zero normrb   r&   )r.   r*   r   rÌ   s     r$   ÚinversezQuaternion.inverse|  s9   € àˆØ�v‰vŒxÜÐUÓVÐVÜ˜‹|˜q §¡£¨1¡™}Ñ-Ð-r1   c                 óä   — 	 | t        |«      }}|dk  r|j                  «       | }}|dk(  r|S t	        dddd«      }|dkD  r|dz  r||z  }||z  }|dz  }|dkD  rŒ|S # t        $ r	 t        cY S w xY w)aë  Finds the pth power of the quaternion.

        Parameters
        ==========

        p : int
            Power to be applied on quaternion.

        Returns
        =======

        Quaternion
            Returns the p-th power of the current quaternion.
            Returns the inverse if p = -1.

        Examples
        ========

        >>> from sympy import Quaternion
        >>> q = Quaternion(1, 2, 3, 4)
        >>> q.pow(4)
        668 + (-224)*i + (-336)*j + (-448)*k

        r   rb   )r   r*   ÚNotImplementedrÓ   rG   )r\   r¯   rÍ   Úress       r$   r®   zQuaternion.powƒ  sš   € ð2	"Øœ ›ˆqˆAð ˆqŠ5Ø—9‘9“;  ˆqˆAà�Š6ØˆHä˜˜A˜q !Ó$ˆØ�!ŠeØ�1ŠuØ�q‘�Ø�‰FˆAØ�!‰GˆAð	 �!‹eð ˆ
øô! ò 	"Ü!Ò!ð	"ús   ‚A ÁA/Á.A/c                 óú  — | }t        |j                  dz  |j                  dz  z   |j                  dz  z   «      }t	        |j
                  «      t        |«      z  }t	        |j
                  «      t        |«      z  |j                  z  |z  }t	        |j
                  «      t        |«      z  |j                  z  |z  }t	        |j
                  «      t        |«      z  |j                  z  |z  }t        ||||«      S )a»  Returns the exponential of $q$, given by $e^q$.

        Returns
        =======

        Quaternion
            The exponential of the quaternion.

        Examples
        ========

        >>> from sympy import Quaternion
        >>> q = Quaternion(1, 2, 3, 4)
        >>> q.exp()
        E*cos(sqrt(29))
        + 2*sqrt(29)*E*sin(sqrt(29))/29*i
        + 3*sqrt(29)*E*sin(sqrt(29))/29*j
        + 4*sqrt(29)*E*sin(sqrt(29))/29*k

        r&   )	r   rS   rT   rU   r
   rR   r   r   rG   )r\   rÍ   Úvector_normrR   rS   rT   rU   s          r$   r
   zQuaternion.exp°  sË   € ð, ˆÜ˜1Ÿ3™3 ™6 A§C¡C¨¡F™?¨Q¯S©S°!©VÑ3Ó4ˆÜ�—‘‹H”s˜;Ó'Ñ'ˆÜ�—‘‹H”s˜;Ó'Ñ'¨!¯#©#Ñ-°Ñ;ˆÜ�—‘‹H”s˜;Ó'Ñ'¨!¯#©#Ñ-°Ñ;ˆÜ�—‘‹H”s˜;Ó'Ñ'¨!¯#©#Ñ-°Ñ;ˆä˜!˜Q  1Ó%Ð%r1   c                 ó¸  — | }t        |j                  dz  |j                  dz  z   |j                  dz  z   «      }|j	                  «       }t        |«      }|j                  t        |j                  |z  «      z  |z  }|j                  t        |j                  |z  «      z  |z  }|j                  t        |j                  |z  «      z  |z  }t        ||||«      S )ag  Returns the logarithm of the quaternion, given by $\log q$.

        Examples
        ========

        >>> from sympy import Quaternion
        >>> q = Quaternion(1, 2, 3, 4)
        >>> q.log()
        log(sqrt(30))
        + 2*sqrt(29)*acos(sqrt(30)/30)/29*i
        + 3*sqrt(29)*acos(sqrt(30)/30)/29*j
        + 4*sqrt(29)*acos(sqrt(30)/30)/29*k

        r&   )	r   rS   rT   rU   r.   Úlnr   rR   rG   )r\   rÍ   rØ   Úq_normrR   rS   rT   rU   s           r$   r   zQuaternion.logÏ  s¹   € ð  ˆÜ˜1Ÿ3™3 ™6 A§C¡C¨¡F™?¨Q¯S©S°!©VÑ3Ó4ˆØ—‘“ˆÜˆv‹JˆØ�C‰C”$�q—s‘s˜V‘|Ó$Ñ$ {Ñ2ˆØ�C‰C”$�q—s‘s˜V‘|Ó$Ñ$ {Ñ2ˆØ�C‰C”$�q—s‘s˜V‘|Ó$Ñ$ {Ñ2ˆä˜!˜Q  1Ó%Ð%r1   c                 óÀ   — | j                   D �cg c]  } |j                  |Ž ‘Œ }}| j                  }|� |j                  |Ž }t        ||«       t	        |d|iŽS c c}w )Nr.   )rZ   Úsubsr[   r0   rG   )r\   rZ   r#   r-   r.   s        r$   Ú
_eval_subszQuaternion._eval_subsé  sa   € Ø+/¯9©9Ö5 a�F�A—F‘F˜D’MÐ5ˆÐ5Ø�z‰zˆØÐØ�4—9‘9˜dÐ#ˆDÜ�H˜dÔ#Ü˜8Ð/¨$Ñ/Ð/ùò 6s   �Ac                 ó‚   — t        |«      }t        | j                  D �cg c]  }|j                  |¬«      ‘Œ c}Ž S c c}w )a  Returns the floating point approximations (decimal numbers) of the quaternion.

        Returns
        =======

        Quaternion
            Floating point approximations of quaternion(self)

        Examples
        ========

        >>> from sympy import Quaternion
        >>> from sympy import sqrt
        >>> q = Quaternion(1/sqrt(1), 1/sqrt(2), 1/sqrt(3), 1/sqrt(4))
        >>> q.evalf()
        1.00000000000000
        + 0.707106781186547*i
        + 0.577350269189626*j
        + 0.500000000000000*k

        )rx   )r   rG   rZ   Úevalf)r\   ÚprecÚnprecÚargs       r$   Ú_eval_evalfzQuaternion._eval_evalfñ  s6   € ô, ˜DÓ!ˆÜ¸$¿)¹)ÖD°3˜CŸI™I¨˜IÕ.ÒDÐEÐEùÒDs   Ÿ<c                 óŠ   — | }|j                  «       \  }}t        j                  |||z  «      }||j                  «       |z  z  S )aY  Computes the pth power in the cos-sin form.

        Parameters
        ==========

        p : int
            Power to be applied on quaternion.

        Returns
        =======

        Quaternion
            The p-th power in the cos-sin form.

        Examples
        ========

        >>> from sympy import Quaternion
        >>> q = Quaternion(1, 2, 3, 4)
        >>> q.pow_cos_sin(4)
        900*cos(4*acos(sqrt(30)/30))
        + 1800*sqrt(29)*sin(4*acos(sqrt(30)/30))/29*i
        + 2700*sqrt(29)*sin(4*acos(sqrt(30)/30))/29*j
        + 3600*sqrt(29)*sin(4*acos(sqrt(30)/30))/29*k

        )Úto_axis_anglerG   rv   r.   )r\   r¯   rÍ   Úvr‘   rÆ   s         r$   Úpow_cos_sinzQuaternion.pow_cos_sin
  sD   € ð< ˆØ—_‘_Ó&‰
ˆˆEÜ×'Ñ'¨¨1¨u©9Ó5ˆØ�Q—V‘V“X˜q‘[Ñ!Ð!r1   c           	      ó¾   — t        t        | j                  g|¢­Ž t        | j                  g|¢­Ž t        | j                  g|¢­Ž t        | j
                  g|¢­Ž «      S )aŽ  Computes integration of quaternion.

        Returns
        =======

        Quaternion
            Integration of the quaternion(self) with the given variable.

        Examples
        ========

        Indefinite Integral of quaternion :

        >>> from sympy import Quaternion
        >>> from sympy.abc import x
        >>> q = Quaternion(1, 2, 3, 4)
        >>> q.integrate(x)
        x + 2*x*i + 3*x*j + 4*x*k

        Definite integral of quaternion :

        >>> from sympy import Quaternion
        >>> from sympy.abc import x
        >>> q = Quaternion(1, 2, 3, 4)
        >>> q.integrate((x, 1, 5))
        4 + 8*i + 12*j + 16*k

        )rG   r   rR   rS   rT   rU   r¹   s     r$   r   zQuaternion.integrate-  sT   € ô: œ) D§F¡FÐ2¨TÒ2´I¸d¿f¹fÐ4LÀtÒ4LÜ# D§F¡FÐ2¨TÒ2´I¸d¿f¹fÐ4LÀtÒ4LóNð 	Nr1   c                 ó  — t        |t        «      rt        j                  |d   |d   «      }n|j	                  «       }|t        d| d   | d   | d   «      z  t        |«      z  }|j                  |j                  |j                  fS )a  Returns the coordinates of the point pin (a 3 tuple) after rotation.

        Parameters
        ==========

        pin : tuple
            A 3-element tuple of coordinates of a point which needs to be
            rotated.
        r : Quaternion or tuple
            Axis and angle of rotation.

            It's important to note that when r is a tuple, it must be of the form
            (axis, angle)

        Returns
        =======

        tuple
            The coordinates of the point after rotation.

        Examples
        ========

        >>> from sympy import Quaternion
        >>> from sympy import symbols, trigsimp, cos, sin
        >>> x = symbols('x')
        >>> q = Quaternion(cos(x/2), 0, 0, sin(x/2))
        >>> trigsimp(Quaternion.rotate_point((1, 1, 1), q))
        (sqrt(2)*cos(x + pi/4), sqrt(2)*sin(x + pi/4), 1)
        >>> (axis, angle) = q.to_axis_angle()
        >>> trigsimp(Quaternion.rotate_point((1, 1, 1), (axis, angle)))
        (sqrt(2)*cos(x + pi/4), sqrt(2)*sin(x + pi/4), 1)

        r   rb   r&   )	rÃ   r‡   rG   rv   rÑ   r   rS   rT   rU   )ÚpinÚrrÍ   Úpouts       r$   Úrotate_pointzQuaternion.rotate_pointM  sy   € ôH �aœÔä×*Ñ*¨1¨Q©4°°1±Ó6‰Að —‘“ˆAØ”:˜a  Q¡¨¨Q©°°Q±Ó8Ñ8¼9ÀQ»<ÑGˆØ—‘˜Ÿ™ §¡Ð'Ð'r1   c                 óŽ  — | }|j                   j                  r|dz  }|j                  «       }t        dt	        |j                   «      z  «      }t        d|j                   |j                   z  z
  «      }t        |j                  |z  «      }t        |j                  |z  «      }t        |j                  |z  «      }|||f}||f}|S )a’  Returns the axis and angle of rotation of a quaternion.

        Returns
        =======

        tuple
            Tuple of (axis, angle)

        Examples
        ========

        >>> from sympy import Quaternion
        >>> q = Quaternion(1, 1, 1, 1)
        >>> (axis, angle) = q.to_axis_angle()
        >>> axis
        (sqrt(3)/3, sqrt(3)/3, sqrt(3)/3)
        >>> angle
        2*pi/3

        r‚   r&   rb   )	rR   Úis_negativerÑ   r   r   r   rS   rT   rU   )	r\   rÍ   r‘   r•   r’   r“   r”   rç   Úts	            r$   ræ   zQuaternion.to_axis_anglez  s©   € ð* ˆØ�3‰3�?Š?Ø�B‘ˆAà�K‰K‹MˆÜ˜œT !§#¡#›Y™Ó'ˆô ��Q—S‘S˜Ÿ™‘W‘Óˆä�Q—S‘S˜1‘WÓˆÜ�Q—S‘S˜1‘WÓˆÜ�Q—S‘S˜1‘WÓˆà��1ˆIˆØ�ˆJˆàˆr1   c           	      ó^  — | }|j                  «       dz  }|rÇ||j                  dz  |j                  dz  z   |j                  dz  z
  |j                  dz  z
  z  }||j                  dz  |j                  dz  z
  |j                  dz  z   |j                  dz  z
  z  }||j                  dz  |j                  dz  z
  |j                  dz  z
  |j                  dz  z   z  }nxdd|z  |j                  dz  |j                  dz  z   z  z
  }dd|z  |j                  dz  |j                  dz  z   z  z
  }dd|z  |j                  dz  |j                  dz  z   z  z
  }d|z  |j                  |j                  z  |j                  |j                  z  z
  z  }d|z  |j                  |j                  z  |j                  |j                  z  z   z  }	d|z  |j                  |j                  z  |j                  |j                  z  z   z  }
d|z  |j                  |j                  z  |j                  |j                  z  z
  z  }d|z  |j                  |j                  z  |j                  |j                  z  z
  z  }d|z  |j                  |j                  z  |j                  |j                  z  z   z  }|st        |||	g|
||g|||gg«      S |\  }}}|||z  z
  ||z  z
  ||	z  z
  }|||
z  z
  ||z  z
  ||z  z
  }|||z  z
  ||z  z
  ||z  z
  }dx}x}}d}t        |||	|g|
|||g||||g||||gg«      S )aÚ  Returns the equivalent rotation transformation matrix of the quaternion
        which represents rotation about the origin if ``v`` is not passed.

        Parameters
        ==========

        v : tuple or None
            Default value: None
        homogeneous : bool
            When True, gives an expression that may be more efficient for
            symbolic calculations but less so for direct evaluation. Both
            formulas are mathematically equivalent.
            Default value: True

        Returns
        =======

        tuple
            Returns the equivalent rotation transformation matrix of the quaternion
            which represents rotation about the origin if v is not passed.

        Examples
        ========

        >>> from sympy import Quaternion
        >>> from sympy import symbols, trigsimp, cos, sin
        >>> x = symbols('x')
        >>> q = Quaternion(cos(x/2), 0, 0, sin(x/2))
        >>> trigsimp(q.to_rotation_matrix())
        Matrix([
        [cos(x), -sin(x), 0],
        [sin(x),  cos(x), 0],
        [     0,       0, 1]])

        Generates a 4x4 transformation matrix (used for rotation about a point
        other than the origin) if the point(v) is passed as an argument.
        éþÿÿÿr&   rb   r   )r.   rR   rS   rT   rU   ri   )r\   rç   ÚhomogeneousrÍ   r•   Úm00Úm11Úm22Úm01Úm02Úm10Úm12Úm20Úm21r’   r“   r”   Úm03Úm13Úm23Úm30Úm31Úm32Úm33s                           r$   Úto_rotation_matrixzQuaternion.to_rotation_matrix¢  s$  € ðN ˆØ�F‰F‹H�b‰Lˆñ Ø�Q—S‘S˜!‘V˜aŸc™c 1™f‘_ q§s¡s¨A¡vÑ-°·±°Q±Ñ6Ñ7ˆCØ�Q—S‘S˜!‘V˜aŸc™c 1™f‘_ q§s¡s¨A¡vÑ-°·±°Q±Ñ6Ñ7ˆCØ�Q—S‘S˜!‘V˜aŸc™c 1™f‘_ q§s¡s¨A¡vÑ-°·±°Q±Ñ6Ñ7‰Cà�a˜‘c˜1Ÿ3™3 ™6 A§C¡C¨¡F™?Ñ+Ñ+ˆCØ�a˜‘c˜1Ÿ3™3 ™6 A§C¡C¨¡F™?Ñ+Ñ+ˆCØ�a˜‘c˜1Ÿ3™3 ™6 A§C¡C¨¡F™?Ñ+Ñ+ˆCà�‰c�1—3‘3�q—s‘s‘7˜QŸS™S §¡™WÑ$Ñ%ˆØ�‰c�1—3‘3�q—s‘s‘7˜QŸS™S §¡™WÑ$Ñ%ˆà�‰c�1—3‘3�q—s‘s‘7˜QŸS™S §¡™WÑ$Ñ%ˆØ�‰c�1—3‘3�q—s‘s‘7˜QŸS™S §¡™WÑ$Ñ%ˆà�‰c�1—3‘3�q—s‘s‘7˜QŸS™S §¡™WÑ$Ñ%ˆØ�‰c�1—3‘3�q—s‘s‘7˜QŸS™S §¡™WÑ$Ñ%ˆáÜ˜C  c˜?¨S°#°s¨O¸cÀ3È¸_ÐMÓNÐNð ‰IˆQ��1à�a˜‘e‘)˜a ™eÑ# a¨¡eÑ+ˆCØ�a˜‘e‘)˜a ™eÑ# a¨¡eÑ+ˆCØ�a˜‘e‘)˜a ™eÑ# a¨¡eÑ+ˆCØÐˆCÐ�#˜ØˆCä˜C  c¨3Ð/°#°s¸CÀÐ1EØ  S¨#Ð.°°c¸3ÀÐ0DðFó Gð Gr1   c                 ó   — | j                   S )am  Returns scalar part($\mathbf{S}(q)$) of the quaternion q.

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

        Given a quaternion $q = a + bi + cj + dk$, returns $\mathbf{S}(q) = a$.

        Examples
        ========

        >>> from sympy.algebras.quaternion import Quaternion
        >>> q = Quaternion(4, 8, 13, 12)
        >>> q.scalar_part()
        4

        )rR   r_   s    r$   Úscalar_partzQuaternion.scalar_partî  s   € ð$ �v‰vˆr1   c                 óZ   — t        d| j                  | j                  | j                  «      S )aû  
        Returns $\mathbf{V}(q)$, the vector part of the quaternion $q$.

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

        Given a quaternion $q = a + bi + cj + dk$, returns $\mathbf{V}(q) = bi + cj + dk$.

        Examples
        ========

        >>> from sympy.algebras.quaternion import Quaternion
        >>> q = Quaternion(1, 1, 1, 1)
        >>> q.vector_part()
        0 + 1*i + 1*j + 1*k

        >>> q = Quaternion(4, 8, 13, 12)
        >>> q.vector_part()
        0 + 8*i + 13*j + 12*k

        r   )rG   rS   rT   rU   r_   s    r$   Úvector_partzQuaternion.vector_part  s!   € ô. ˜!˜TŸV™V T§V¡V¨T¯V©VÓ4Ð4r1   c                 ó–   — | j                  «       j                  «       }t        d|j                  |j                  |j
                  «      S )aˆ  
        Returns $\mathbf{Ax}(q)$, the axis of the quaternion $q$.

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

        Given a quaternion $q = a + bi + cj + dk$, returns $\mathbf{Ax}(q)$  i.e., the versor of the vector part of that quaternion
        equal to $\mathbf{U}[\mathbf{V}(q)]$.
        The axis is always an imaginary unit with square equal to $-1 + 0i + 0j + 0k$.

        Examples
        ========

        >>> from sympy.algebras.quaternion import Quaternion
        >>> q = Quaternion(1, 1, 1, 1)
        >>> q.axis()
        0 + sqrt(3)/3*i + sqrt(3)/3*j + sqrt(3)/3*k

        See Also
        ========

        vector_part

        r   )r	  rÑ   rG   rS   rT   rU   )r\   Úaxiss     r$   r  zQuaternion.axis  s8   € ð2 ×ÑÓ!×+Ñ+Ó-ˆä˜!˜TŸV™V T§V¡V¨T¯V©VÓ4Ð4r1   c                 ó.   — | j                   j                  S )a  
        Returns true if the quaternion is pure, false if the quaternion is not pure
        or returns none if it is unknown.

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

        A pure quaternion (also a vector quaternion) is a quaternion with scalar
        part equal to 0.

        Examples
        ========

        >>> from sympy.algebras.quaternion import Quaternion
        >>> q = Quaternion(0, 8, 13, 12)
        >>> q.is_pure()
        True

        See Also
        ========
        scalar_part

        )rR   Úis_zeror_   s    r$   Úis_purezQuaternion.is_pure8  s   € ð2 �v‰v�~‰~Ðr1   c                 ó6   — | j                  «       j                  S )a‚  
        Returns true if the quaternion is a zero quaternion or false if it is not a zero quaternion
        and None if the value is unknown.

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

        A zero quaternion is a quaternion with both scalar part and
        vector part equal to 0.

        Examples
        ========

        >>> from sympy.algebras.quaternion import Quaternion
        >>> q = Quaternion(1, 0, 0, 0)
        >>> q.is_zero_quaternion()
        False

        >>> q = Quaternion(0, 0, 0, 0)
        >>> q.is_zero_quaternion()
        True

        See Also
        ========
        scalar_part
        vector_part

        )r.   r  r_   s    r$   rƒ   zQuaternion.is_zero_quaternionS  s   € ð< �y‰y‹{×"Ñ"Ð"r1   c                 ót   — dt        | j                  «       j                  «       | j                  «       «      z  S )a7  
        Returns the angle of the quaternion measured in the real-axis plane.

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

        Given a quaternion $q = a + bi + cj + dk$ where $a$, $b$, $c$ and $d$
        are real numbers, returns the angle of the quaternion given by

        .. math::
            \theta := 2 \operatorname{atan_2}\left(\sqrt{b^2 + c^2 + d^2}, {a}\right)

        Examples
        ========

        >>> from sympy.algebras.quaternion import Quaternion
        >>> q = Quaternion(1, 4, 4, 4)
        >>> q.angle()
        2*atan(4*sqrt(3))

        r&   )r   r	  r.   r  r_   s    r$   r‘   zQuaternion.angles  s1   € ð. ”5˜×)Ñ)Ó+×0Ñ0Ó2°D×4DÑ4DÓ4FÓGÑGÐGr1   c                 ó&  — | j                  «       s|j                  «       rt        d«      ‚t        | j                  «       |j                  «       z
  j                  «       | j                  «       |j                  «       z   j                  «       g«      S )aS  
        Returns True if the transformation arcs represented by the input quaternions happen in the same plane.

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

        Two quaternions are said to be coplanar (in this arc sense) when their axes are parallel.
        The plane of a quaternion is the one normal to its axis.

        Parameters
        ==========

        other : a Quaternion

        Returns
        =======

        True : if the planes of the two quaternions are the same, apart from its orientation/sign.
        False : if the planes of the two quaternions are not the same, apart from its orientation/sign.
        None : if plane of either of the quaternion is unknown.

        Examples
        ========

        >>> from sympy.algebras.quaternion import Quaternion
        >>> q1 = Quaternion(1, 4, 4, 4)
        >>> q2 = Quaternion(3, 8, 8, 8)
        >>> Quaternion.arc_coplanar(q1, q2)
        True

        >>> q1 = Quaternion(2, 8, 13, 12)
        >>> Quaternion.arc_coplanar(q1, q2)
        False

        See Also
        ========

        vector_coplanar
        is_pure

        z)Neither of the given quaternions can be 0)rƒ   r*   r   r  rž   s     r$   Úarc_coplanarzQuaternion.arc_coplanar�  sp   € ðT ×#Ñ#Ô%¨5×+CÑ+CÔ+EÜÐHÓIÐIä˜$Ÿ)™)›+¨¯
©
«Ñ4×HÑHÓJÈTÏYÉYË[Ð[`×[eÑ[eÓ[gÑMg×L{ÑL{ÓL}Ð~ÓÐr1   c                 óÄ  — t        |j                  «       «      s2t        |j                  «       «      st        |j                  «       «      rt        d«      ‚t        |j                  |j
                  |j                  g|j                  |j
                  |j                  g|j                  |j
                  |j                  gg«      j                  «       }|j                  S )a"  
        Returns True if the axis of the pure quaternions seen as 3D vectors
        ``q1``, ``q2``, and ``q3`` are coplanar.

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

        Three pure quaternions are vector coplanar if the quaternions seen as 3D vectors are coplanar.

        Parameters
        ==========

        q1
            A pure Quaternion.
        q2
            A pure Quaternion.
        q3
            A pure Quaternion.

        Returns
        =======

        True : if the axis of the pure quaternions seen as 3D vectors
        q1, q2, and q3 are coplanar.
        False : if the axis of the pure quaternions seen as 3D vectors
        q1, q2, and q3 are not coplanar.
        None : if the axis of the pure quaternions seen as 3D vectors
        q1, q2, and q3 are coplanar is unknown.

        Examples
        ========

        >>> from sympy.algebras.quaternion import Quaternion
        >>> q1 = Quaternion(0, 4, 4, 4)
        >>> q2 = Quaternion(0, 8, 8, 8)
        >>> q3 = Quaternion(0, 24, 24, 24)
        >>> Quaternion.vector_coplanar(q1, q2, q3)
        True

        >>> q1 = Quaternion(0, 8, 16, 8)
        >>> q2 = Quaternion(0, 8, 3, 12)
        >>> Quaternion.vector_coplanar(q1, q2, q3)
        False

        See Also
        ========

        axis
        is_pure

        ú"The given quaternions must be pure)	r   r  r*   ri   rS   rT   rU   r—   r  )rQ   rÅ   rÆ   Úq3r˜   s        r$   Úvector_coplanarzQuaternion.vector_coplanar¼  s–   € ôl �R—Z‘Z“\Ô"¤i°·
±
³Ô&=ÄÈ2Ï:É:Ë<ÔAXÜÐAÓBÐBä�R—T‘T˜2Ÿ4™4 §¡Ð&¨¯©¨r¯t©t°R·T±TÐ(:¸R¿T¹TÀ2Ç4Á4ÈÏÉÐ<NÐOÓP×TÑTÓVˆØ�y‰yÐr1   c                 ó®   — t        | j                  «       «      st        |j                  «       «      rt        d«      ‚| |z  || z  z
  j                  «       S )aº  
        Returns True if the two pure quaternions seen as 3D vectors are parallel.

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

        Two pure quaternions are called parallel when their vector product is commutative which
        implies that the quaternions seen as 3D vectors have same direction.

        Parameters
        ==========

        other : a Quaternion

        Returns
        =======

        True : if the two pure quaternions seen as 3D vectors are parallel.
        False : if the two pure quaternions seen as 3D vectors are not parallel.
        None : if the two pure quaternions seen as 3D vectors are parallel is unknown.

        Examples
        ========

        >>> from sympy.algebras.quaternion import Quaternion
        >>> q = Quaternion(0, 4, 4, 4)
        >>> q1 = Quaternion(0, 8, 8, 8)
        >>> q.parallel(q1)
        True

        >>> q1 = Quaternion(0, 8, 13, 12)
        >>> q.parallel(q1)
        False

        z%The provided quaternions must be pure©r   r  r*   rƒ   rž   s     r$   ÚparallelzQuaternion.parallelø  sH   € ôJ �T—\‘\“^Ô$¬	°%·-±-³/Ô(BÜÐDÓEÐEà�U‘
˜U 4™ZÑ'×;Ñ;Ó=Ð=r1   c                 ó®   — t        | j                  «       «      st        |j                  «       «      rt        d«      ‚| |z  || z  z   j                  «       S )a|  
        Returns the orthogonality of two quaternions.

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

        Two pure quaternions are called orthogonal when their product is anti-commutative.

        Parameters
        ==========

        other : a Quaternion

        Returns
        =======

        True : if the two pure quaternions seen as 3D vectors are orthogonal.
        False : if the two pure quaternions seen as 3D vectors are not orthogonal.
        None : if the two pure quaternions seen as 3D vectors are orthogonal is unknown.

        Examples
        ========

        >>> from sympy.algebras.quaternion import Quaternion
        >>> q = Quaternion(0, 4, 4, 4)
        >>> q1 = Quaternion(0, 8, 8, 8)
        >>> q.orthogonal(q1)
        False

        >>> q1 = Quaternion(0, 2, 2, 0)
        >>> q = Quaternion(0, 2, -2, 0)
        >>> q.orthogonal(q1)
        True

        r  r  rž   s     r$   Ú
orthogonalzQuaternion.orthogonal"  sH   € ôJ �T—\‘\“^Ô$¬	°%·-±-³/Ô(BÜÐAÓBÐBà�U‘
˜U 4™ZÑ'×;Ñ;Ó=Ð=r1   c                 óD   — | j                  «       | j                  «       z  S )a’  
        Returns the index vector of the quaternion.

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

        The index vector is given by $\mathbf{T}(q)$, the norm (or magnitude) of
        the quaternion $q$, multiplied by $\mathbf{Ax}(q)$, the axis of $q$.

        Returns
        =======

        Quaternion: representing index vector of the provided quaternion.

        Examples
        ========

        >>> from sympy.algebras.quaternion import Quaternion
        >>> q = Quaternion(2, 4, 2, 4)
        >>> q.index_vector()
        0 + 4*sqrt(10)/3*i + 2*sqrt(10)/3*j + 4*sqrt(10)/3*k

        See Also
        ========

        axis
        norm

        )r.   r  r_   s    r$   Úindex_vectorzQuaternion.index_vectorL  s   € ð> �y‰y‹{˜TŸY™Y›[Ñ(Ð(r1   c                 ó4   — t        | j                  «       «      S )aj  
        Returns the natural logarithm of the norm(magnitude) of the quaternion.

        Examples
        ========

        >>> from sympy.algebras.quaternion import Quaternion
        >>> q = Quaternion(2, 4, 2, 4)
        >>> q.mensor()
        log(2*sqrt(10))
        >>> q.norm()
        2*sqrt(10)

        See Also
        ========

        norm

        )rÚ   r.   r_   s    r$   ÚmensorzQuaternion.mensorm  s   € ô* �$—)‘)“+‹Ðr1   )r   r   r   r   TN)F)TF)NT)AÚ__name__Ú
__module__Ú__qualname__Ú__doc__Ú_op_priorityrJ   rN   rP   ÚpropertyrR   rS   rT   rU   rV   rj   rl   ro   Úclassmethodrs   r   r�   rv   rš   r    r£   r¦   rª   r¬   r°   r²   rµ   r·   rº   r¿   r�   rÈ   Ústaticmethodr©   rÎ   r.   rÑ   rÓ   r®   r
   r   rÞ   rä   rè   r   rî   ræ   r  r  r	  r  r  rƒ   r‘   r  r  r  r  r  r  Ú__classcell__)rX   s   @r$   rG   rG   :   s  ø„ ñ/ð` €Là€Nõò"ðH ñó ðð ñó ðð ñó ðð ñó ðð ñ ó ð ð ñ/4ó ð/4ðb ñ44ó ð44ól/%ðb ñ()ó ð()ðT ñ=*ó ð=*ó~L!ð\ ñ(ó ð(ðT ñ)&ó ð)&òVòò"ò8ò8òò>ò)ò)ò%òLò4"òl'8ðR ñI%ó ðI%òV?ò
ò ò
.ò+òZ&ò>&ò40òFò2!"òFNð@ ñ*(ó ð*(òX&óPJGòXò(5ò25ò:ò6#ò@Hò4-@ð^ ñ9ó ð9òv(>òT(>òT)öBr1   rG   N)-Úsympy.core.numbersr   Úsympy.core.singletonr   Úsympy.core.relationalr   Ú$sympy.functions.elementary.complexesr   r   r   r	   Ú&sympy.functions.elementary.exponentialr
   r   rÚ   Ú(sympy.functions.elementary.miscellaneousr   Ú(sympy.functions.elementary.trigonometricr   r   r   r   r   Úsympy.simplify.trigsimpr   Úsympy.integrals.integralsr   Úsympy.matrices.denser   ri   Úsympy.core.sympifyr   r   Úsympy.core.exprr   Úsympy.core.logicr   r   Úsympy.utilities.miscr   Úmpmath.libmp.libmpfr   r0   rE   rG   r(   r1   r$   ú<module>r8     sS   ðÝ 'Ý "Ý 'ß JÓ Jß CÝ 9ß HÑ Hß ?Ý ,Ý /Ý =ß 0Ý  ß 0Ý 'å +ò=òô6H�õ Hr1   