U
    ZÊ¹j§¹  ã                   @   s  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d„ Z*dd„ Z+G dd„ de"ƒZ,dS )é    )Ú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                 C   sb   |dk	r^|j r^|jdkr tdƒ‚tdd„ | D ƒƒ}|r^t|d tdd„ | D ƒƒƒdkr^tdƒ‚dS )	z$validate if input norm is consistentNFzInput norm must be positive.c                 s   s   | ]}|j o|jd kV  qdS )TN)Ú	is_numberZis_real©Ú.0Úi© r    úX/var/www/html/bwave/python/venv/lib/python3.8/site-packages/sympy/algebras/quaternion.pyÚ	<genexpr>   s     z_check_norm.<locals>.<genexpr>é   c                 s   s   | ]}|d  V  qdS )r#   Nr    r   r    r    r!   r"      s     zIncompatible value for norm.)r   Zis_positiveÚ
ValueErrorÚallr   Úsum)ÚelementsÚnormZ	numericalr    r    r!   Ú_check_norm   s    
$r)   c                 C   s    t | ƒtkrtdƒ‚t| ƒdkr.td | ¡ƒ‚|  ¡ }|  ¡ }|sN|sNtdƒ‚|  ¡ \}}}||ksl||krttdƒ‚t| ƒtdƒ }|rœtd d 	|¡¡ƒ‚|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 differentZxyzXYZzNExpected axes from `seq` to be from ['x', 'y', 'z'] or ['X', 'Y', 'Z'], got {}Ú )
ÚtypeÚstrr$   ÚlenÚformatÚisupperÚislowerÚlowerÚsetÚjoin)ÚseqZ	intrinsicÚ	extrinsicr   ÚjÚkÚbadr    r    r!   Ú_is_extrinsic   s"    þr:   c                       s  e Zd ZdZdZdZdu‡ fdd„	Zd	d
„ Zedd„ ƒZ	edd„ ƒZ
edd„ ƒZedd„ ƒZedd„ ƒZedd„ ƒZedd„ ƒZdvdd„Zedd„ ƒZedd„ ƒZdwdd „Zed!d"„ ƒZed#d$„ ƒZd%d&„ Zd'd(„ Zd)d*„ Zd+d,„ Zd-d.„ Zd/d0„ Zd1d2„ Zd3d4„ Zd5d6„ Zd7d8„ Z d9d:„ Z!d;d<„ Z"d=d>„ Z#e$d?d@„ ƒZ%dAdB„ Z&dCdD„ Z'dEdF„ Z(dGdH„ Z)dIdJ„ Z*dKdL„ Z+dMdN„ Z,dOdP„ Z-dQdR„ Z.dSdT„ Z/dUdV„ Z0e$dWdX„ ƒZ1dYdZ„ Z2dxd[d\„Z3d]d^„ Z4d_d`„ Z5dadb„ Z6dcdd„ Z7dedf„ Z8dgdh„ Z9didj„ Z:edkdl„ ƒZ;dmdn„ Z<dodp„ Z=dqdr„ Z>dsdt„ Z?‡  Z@S )yÚ
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      &@Fr   TNc                    sd   t t||||fƒ\}}}}tdd„ ||||fD ƒƒr<tdƒ‚tƒ  | ||||¡}||_| |¡ |S )Nc                 s   s   | ]}|j d kV  qdS )FN)Úis_commutativer   r    r    r!   r"   r   s     z%Quaternion.__new__.<locals>.<genexpr>z arguments have to be commutative)Úmapr   Úanyr$   ÚsuperÚ__new__Ú_real_fieldÚset_norm)ÚclsÚaÚbÚcÚdÚ
real_fieldr(   Úobj©Ú	__class__r    r!   r@   o   s    
zQuaternion.__new__c                 C   s   t |ƒ}t| j|ƒ || _dS )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   r)   ÚargsÚ_norm)Úselfr(   r    r    r!   rB   y   s     zQuaternion.set_normc                 C   s
   | j d S )Nr   ©rL   ©rN   r    r    r!   rD   �   s    zQuaternion.ac                 C   s
   | j d S )Né   rO   rP   r    r    r!   rE   ¡   s    zQuaternion.bc                 C   s
   | j d S )Nr#   rO   rP   r    r    r!   rF   ¥   s    zQuaternion.cc                 C   s
   | j d S )Nr*   rO   rP   r    r    r!   rG   ©   s    zQuaternion.dc                 C   s   | j S ©N)rA   rP   r    r    r!   rH   ­   s    zQuaternion.real_fieldc                 C   s\   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]])
        ©ÚMatrixrD   rE   rF   rG   rP   r    r    r!   Úproduct_matrix_left±   s    ,üzQuaternion.product_matrix_leftc                 C   s\   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]])
        rS   rP   r    r    r!   Úproduct_matrix_rightã   s    1üzQuaternion.product_matrix_rightc                 C   s$   |rt | jdd… ƒS t | jƒS d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]])

        rQ   N)rT   rL   )rN   Zvector_onlyr    r    r!   Ú	to_Matrix  s    ,zQuaternion.to_Matrixc                 C   sF   t |ƒ}|dkr&|dkr&td |¡ƒ‚|dkr:td|žŽ S t|Ž S d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

        r*   é   z7Input elements must have length 3 or 4, got {} elementsr   N)r   )r.   r$   r/   r;   )rC   r'   Úlengthr    r    r!   Úfrom_MatrixK  s    !ÿzQuaternion.from_Matrixc           
         s¸   t |ƒdkrtdƒ‚t|ƒ}| ¡ \‰ ‰‰‡ fdd„dD ƒ}‡fdd„dD ƒ}‡fdd„dD ƒ}|  ||d ¡}|  ||d	 ¡}|  ||d
 ¡}	|r¤t|	| | ƒS t|| |	 ƒS dS )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

        r*   z3 angles must be given.c                    s   g | ]}|ˆ krd nd‘qS ©rQ   r   r    ©r   Ún)r   r    r!   Ú
<listcomp>¨  s     z)Quaternion.from_euler.<locals>.<listcomp>Úxyzc                    s   g | ]}|ˆ krd nd‘qS r[   r    r\   )r7   r    r!   r^   ©  s     c                    s   g | ]}|ˆ krd nd‘qS r[   r    r\   )r8   r    r!   r^   ª  s     r   rQ   r#   N)r.   r$   r:   r2   Úfrom_axis_angler   )
rC   Úanglesr5   r6   ÚeiZejZekZqiZqjZqkr    )r   r7   r8   r!   Ú
from_eulerv  s    +zQuaternion.from_eulerc                 C   sB  |   ¡ rtdƒ‚dddg}t|ƒ}| ¡ \}}}d |¡d }d |¡d }d |¡d }|sh|| }}||k}	|	r€d| | }|| ||  ||  d }
| j| j| j| jg}|d }|| }|| }|| |
 }|	sü|| || || || f\}}}}|�r€|	�rB|  	¡ d }t
|| ||  ||  ||  | ƒ|d< n<d|  	¡ d  }t|| ||  ||  ||  | ƒ|d< nNdtt|| ||  ƒt|| ||  ƒƒ |d< |	�sÎ|d  tjd 8  < d}t|tjƒ�ròt|tjƒ�ròd}t|tjƒ�rt|tjƒ�rd}|dk�r¢|�rTt||ƒt||ƒ |d< t||ƒt||ƒ |d< nLt|| ||  || ||  ƒ|d< t|| ||  || ||  ƒ|d< nftj|d|  < |dk�rÔdt||ƒ |d| < n4dt||ƒ |d| < |d|   |�r dnd9  < |	�s|d  |
9  < |�r6t|ddd… ƒS t|ƒS d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_   rQ   é   r#   éÿÿÿÿN)Úis_zero_quaternionr$   r:   r2   ÚindexrD   rE   rF   rG   r(   r   r   r   r   r   ÚPir   ZZeroÚtuple)rN   r5   Zangle_additionZavoid_square_rootra   r6   r   r7   r8   Z	symmetricr   r'   rD   rE   rF   rG   Zn2Úcaser    r    r!   Úto_euler¶  sf    @

$..2
&(
zQuaternion.to_eulerc                 C   s„   |\}}}t |d |d  |d  ƒ}|| || ||   }}}t|tj ƒ}t|tj ƒ}|| }	|| }
|| }| ||	|
|ƒ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   ZHalfr   )rC   ZvectorÚangleÚxÚyÚzr(   ÚsrD   rE   rF   rG   r    r    r!   r`   D  s    
zQuaternion.from_axis_anglec                 C   sø   |  ¡ tddƒ }t||d  |d  |d  ƒd }t||d  |d  |d  ƒd }t||d  |d  |d  ƒd }t||d  |d  |d  ƒd }|t|d |d  ƒ }|t|d	 |d
  ƒ }|t|d |d  ƒ }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

        rQ   r*   )r   r   )rQ   rQ   )r#   r#   r#   )r#   rQ   )rQ   r#   )r   r#   )r#   r   r[   )r   rQ   )Údetr   r   r   r;   )rC   ÚMZabsQrD   rE   rF   rG   r    r    r!   Úfrom_rotation_matrixo  s    $$$$zQuaternion.from_rotation_matrixc                 C   s
   |   |¡S rR   ©Úadd©rN   Úotherr    r    r!   Ú__add__›  s    zQuaternion.__add__c                 C   s
   |   |¡S rR   rt   rv   r    r    r!   Ú__radd__ž  s    zQuaternion.__radd__c                 C   s   |   |d ¡S ©Nre   rt   rv   r    r    r!   Ú__sub__¡  s    zQuaternion.__sub__c                 C   s   |   | t|ƒ¡S rR   ©Ú_generic_mulr   rv   r    r    r!   Ú__mul__¤  s    zQuaternion.__mul__c                 C   s   |   t|ƒ| ¡S rR   r|   rv   r    r    r!   Ú__rmul__§  s    zQuaternion.__rmul__c                 C   s
   |   |¡S rR   )Úpow)rN   Úpr    r    r!   Ú__pow__ª  s    zQuaternion.__pow__c                 C   s   t | j | j | j | j ƒS rR   )r;   rD   rE   rF   rG   rP   r    r    r!   Ú__neg__­  s    zQuaternion.__neg__c                 C   s   | t |ƒd  S rz   ©r   rv   r    r    r!   Ú__truediv__°  s    zQuaternion.__truediv__c                 C   s   t |ƒ| d  S rz   r„   rv   r    r    r!   Ú__rtruediv__³  s    zQuaternion.__rtruediv__c                 G   s
   | j |Ž S rR   r   ©rN   rL   r    r    r!   Ú_eval_Integral¶  s    zQuaternion._eval_Integralc                    s(   ˆ   dd¡ | j‡ ‡fdd„| jD ƒŽ S )NÚevaluateTc                    s   g | ]}|j ˆˆ Ž‘qS r    )Údiff)r   rD   ©ÚkwargsÚsymbolsr    r!   r^   »  s     z#Quaternion.diff.<locals>.<listcomp>)Ú
setdefaultÚfuncrL   )rN   r�   rŒ   r    r‹   r!   rŠ   ¹  s    zQuaternion.diffc                 C   sž   | }t |ƒ}t|tƒsp|jrH|jrHtt|ƒ|j t|ƒ|j |j	|j
ƒS |jrht|j| |j|j	|j
ƒS tdƒ‚t|j|j |j|j |j	|j	 |j
|j
 ƒ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   Ú
isinstancer;   rH   Ú
is_complexr   rD   r   rE   rF   rG   r<   r$   )rN   rw   Úq1Úq2r    r    r!   ru   ½  s    '
&$ÿzQuaternion.addc                 C   s   |   | 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|   rv   r    r    r!   Úmuló  s    'zQuaternion.mulc                 C   sØ  t | tƒst |tƒs| | S t | tƒs€|jrL| jrLtt| ƒt| ƒddƒ| S | jrxt| |j | |j | |j	 | |j
 ƒS tdƒ‚t |tƒsä| jr°|jr°| tt|ƒt|ƒddƒ S |jrÜt|| j || j || j	 || j
 ƒS tdƒ‚| jdk�r|jdk�rd}n|  ¡ | ¡  }t| j |j | j	|j	  | j
|j
  | j|j  | j|j | j	|j
  | j
|j	  | j|j  | j |j
 | j	|j  | j
|j  | j|j	  | j|j	 | j	|j  | j
|j  | j|j
  |d�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�   r;   rH   r‘   r   r   r<   rD   rE   rF   rG   r$   rM   r(   )r’   r“   r(   r    r    r!   r}     s.    +
&
&2.0.üzQuaternion._generic_mulc                 C   s&   | }t |j|j |j |j |jd�S )z(Returns the conjugate of the quaternion.r•   )r;   rD   rE   rF   rG   rM   ©rN   Úqr    r    r!   Ú_eval_conjugateh  s    zQuaternion._eval_conjugatec                 C   sD   | j dkr>| }tt|jd |jd  |jd  |jd  ƒƒS | j S )z#Returns the norm of the quaternion.Nr#   )rM   r   r   rD   rE   rF   rG   r–   r    r    r!   r(   m  s    
0zQuaternion.normc                 C   s   | }|d|  ¡   S )z.Returns the normalized form of the quaternion.rQ   r•   r–   r    r    r!   Ú	normalizew  s    zQuaternion.normalizec                 C   s,   | }|  ¡ stdƒ‚t|ƒd|  ¡ d   S )z&Returns the inverse of the quaternion.z6Cannot compute inverse for a quaternion with zero normrQ   r#   )r(   r$   r   r–   r    r    r!   Úinverse|  s    zQuaternion.inversec                 C   sŒ   z| t |ƒ }}W n tk
r*   t Y S X |dk rD| ¡ |  }}|dkrP|S tddddƒ}|dkrˆ|d@ rv||9 }||9 }|dL }q^|S )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   rQ   )r   r$   ÚNotImplementedrš   r;   )rN   r�   r—   Úresr    r    r!   r€   ƒ  s    

zQuaternion.powc                 C   sš   | }t |jd |jd  |jd  ƒ}t|jƒt|ƒ }t|jƒt|ƒ |j | }t|jƒt|ƒ |j | }t|jƒt|ƒ |j | }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   rE   rF   rG   r	   rD   r   r   r;   )rN   r—   Úvector_normrD   rE   rF   rG   r    r    r!   r	   °  s    "zQuaternion.expc                 C   sŒ   | }t |jd |jd  |jd  ƒ}| ¡ }t|ƒ}|jt|j| ƒ | }|jt|j| ƒ | }|jt|j| ƒ | }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   rE   rF   rG   r(   Úlnr   rD   r;   )rN   r—   r�   Zq_normrD   rE   rF   rG   r    r    r!   r
   Ï  s    "zQuaternion.logc                    sD   ‡ fdd„| j D ƒ}| j}|d k	r,|jˆ Ž }t||ƒ t|d|iŽS )Nc                    s   g | ]}|j ˆ Ž ‘qS r    )Úsubsr   rO   r    r!   r^   ê  s     z)Quaternion._eval_subs.<locals>.<listcomp>r(   )rL   rM   rŸ   r)   r;   )rN   rL   r'   r(   r    rO   r!   Ú
_eval_subsé  s    

zQuaternion._eval_subsc                    s    t |ƒ‰ t‡ fdd„| jD ƒŽ S )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

        c                    s   g | ]}|j ˆ d �‘qS ))r]   )Zevalf)r   Úarg©Znprecr    r!   r^     s     z*Quaternion._eval_evalf.<locals>.<listcomp>)r   r;   rL   )rN   Úprecr    r¢   r!   Ú_eval_evalfñ  s    zQuaternion._eval_evalfc                 C   s0   | }|  ¡ \}}t ||| ¡}|| ¡ |  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_angler;   r`   r(   )rN   r�   r—   Úvrl   r“   r    r    r!   Úpow_cos_sin
  s    zQuaternion.pow_cos_sinc                 G   s>   t t| jf|žŽ t| jf|žŽ t| jf|žŽ t| jf|žŽ ƒ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

        )r;   r   rD   rE   rF   rG   r‡   r    r    r!   r   -  s     ÿzQuaternion.integratec                 C   s^   t |tƒr t |d |d ¡}n| ¡ }|td| d | d | d ƒ t|ƒ }|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   rQ   r#   )	r�   ri   r;   r`   r™   r   rE   rF   rG   )ZpinÚrr—   Zpoutr    r    r!   Úrotate_pointN  s
    $
&zQuaternion.rotate_pointc           	      C   s‚   | }|j jr|d }| ¡ }tdt|j ƒ ƒ}td|j |j   ƒ}t|j| ƒ}t|j| ƒ}t|j| ƒ}|||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

        re   r#   rQ   )	rD   Zis_negativer™   r   r   r   rE   rF   rG   )	rN   r—   rl   rp   rm   rn   ro   r¦   Útr    r    r!   r¥   {  s    
zQuaternion.to_axis_anglec                 C   s‚  | }|  ¡ d }|rš||jd |jd  |jd  |jd   }||jd |jd  |jd  |jd   }||jd |jd  |jd  |jd   }n`dd| |jd |jd    }dd| |jd |jd    }dd| |jd |jd    }d| |j|j |j|j   }d| |j|j |j|j   }	d| |j|j |j|j   }
d| |j|j |j|j   }d| |j|j |j|j   }d| |j|j |j|j   }|�sàt|||	g|
||g|||ggƒS |\}}}|||  ||  ||	  }|||
  ||  ||  }|||  ||  ||  }d } }}d}t|||	|g|
|||g||||g||||ggƒS d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#   rQ   r   N)r(   rD   rE   rF   rG   rT   )rN   r¦   Zhomogeneousr—   rp   Zm00Zm11Zm22Zm01Zm02Zm10Zm12Zm20Zm21rm   rn   ro   Zm03Zm13Zm23Zm30Zm31Zm32Zm33r    r    r!   Úto_rotation_matrix£  s6    ',,.          

 
ÿzQuaternion.to_rotation_matrixc                 C   s   | 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

        )rD   rP   r    r    r!   Úscalar_partï  s    zQuaternion.scalar_partc                 C   s   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   )r;   rE   rF   rG   rP   r    r    r!   Úvector_part  s    zQuaternion.vector_partc                 C   s    |   ¡  ¡ }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™   r;   rE   rF   rG   )rN   Úaxisr    r    r!   r¯     s    zQuaternion.axisc                 C   s   | 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

        )rD   Úis_zerorP   r    r    r!   Úis_pure9  s    zQuaternion.is_purec                 C   s
   |   ¡ 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°   rP   r    r    r!   rf   T  s    zQuaternion.is_zero_quaternionc                 C   s   dt |  ¡  ¡ |  ¡ ƒ 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­   rP   r    r    r!   rl   t  s    zQuaternion.anglec                 C   sD   |   ¡ s|  ¡ rtdƒ‚t|  ¡ | ¡    ¡ |  ¡ | ¡    ¡ 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)rf   r$   r   r¯   rv   r    r    r!   Úarc_coplanarŽ  s    *zQuaternion.arc_coplanarc                 C   sh   t | ¡ ƒs$t | ¡ ƒs$t | ¡ ƒr,tdƒ‚t|j|j|jg|j|j|jg|j|j|jggƒ ¡ }|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$   rT   rE   rF   rG   rq   r°   )rC   r’   r“   Zq3rr   r    r    r!   Úvector_coplanar½  s    6$6zQuaternion.vector_coplanarc                 C   s4   t |  ¡ ƒst | ¡ ƒr tdƒ‚| | ||    ¡ 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$   rf   rv   r    r    r!   Úparallelù  s    %zQuaternion.parallelc                 C   s4   t |  ¡ ƒst | ¡ ƒr tdƒ‚| | ||    ¡ 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µ   rv   r    r    r!   Ú
orthogonal#  s    %zQuaternion.orthogonalc                 C   s   |   ¡ |  ¡  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¯   rP   r    r    r!   Úindex_vectorM  s    zQuaternion.index_vectorc                 C   s   t |  ¡ ƒ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(   rP   r    r    r!   Úmensorn  s    zQuaternion.mensor)r   r   r   r   TN)F)TF)NT)AÚ__name__Ú
__module__Ú__qualname__Ú__doc__Z_op_priorityr<   r@   rB   ÚpropertyrD   rE   rF   rG   rH   rU   rV   rW   ÚclassmethodrZ   rc   rk   r`   rs   rx   ry   r{   r~   r   r‚   rƒ   r…   r†   rˆ   rŠ   ru   r”   Ústaticmethodr}   r˜   r(   r™   rš   r€   r	   r
   r    r¤   r§   r   r©   r¥   r¬   r­   r®   r¯   r±   rf   rl   r²   r´   r¶   r·   r¸   r¹   Ú__classcell__r    r    rJ   r!   r;   :   s’   0
$





1
6
1
*
?
 
*
+6)
K
-#!
,(
L /
;**!r;   N)-Zsympy.core.numbersr   Zsympy.core.singletonr   Zsympy.core.relationalr   Z$sympy.functions.elementary.complexesr   r   r   r   Z&sympy.functions.elementary.exponentialr	   r
   rž   Z(sympy.functions.elementary.miscellaneousr   Z(sympy.functions.elementary.trigonometricr   r   r   r   r   Zsympy.simplify.trigsimpr   Zsympy.integrals.integralsr   Zsympy.matrices.denser   rT   Zsympy.core.sympifyr   r   Zsympy.core.exprr   Zsympy.core.logicr   r   Zsympy.utilities.miscr   Zmpmath.libmp.libmpfr   r)   r:   r;   r    r    r    r!   Ú<module>   s$   