a
    RG5d}                     @   s   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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$ G dd deZ%dS )    )Rational)S)	conjugateimresign)explog)sqrt)acoscossinatan2)trigsimp	integrate)MutableDenseMatrix)sympify_sympify)Expr)	fuzzy_notfuzzy_or)prec_to_dpsc                   @   s  e Zd ZdZdZdZded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dd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- Zd.d/ Zed0d1 Zd2d3 Zd4d5 Z d6d7 Z!d8d9 Z"d:d; Z#d<d= Z$d>d? Z%d@dA Z&dBdC Z'dDdE Z(edFdG Z)dHdI Z*dfdKdLZ+dMdN Z,dOdP Z-dQdR Z.dSdT Z/dUdV Z0dWdX Z1dYdZ Z2ed[d\ Z3d]d^ Z4d_d` Z5dadb Z6dcdd Z7dJS )g
QuaternionaJ  Provides basic quaternion operations.
    Quaternion objects can be instantiated as Quaternion(a, b, c, d)
    as in (a + b*i + c*j + d*k).

    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

    References
    ==========

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

    g      &@Fr   Tc                 C   sv   t t||||f\}}}}tdd ||||fD r>tdn4t| ||||}||_||_||_||_	||_
|S d S )Nc                 s   s   | ]}|j d u V  qdS )FN)is_commutative).0i r   U/var/www/html/django/DPS/env/lib/python3.9/site-packages/sympy/algebras/quaternion.py	<genexpr>8       z%Quaternion.__new__.<locals>.<genexpr>z arguments have to be commutative)mapr   any
ValueErrorr   __new___a_b_c_d_real_field)clsabcd
real_fieldobjr   r   r   r$   5   s    
zQuaternion.__new__c                 C   s   | j S N)r%   selfr   r   r   r+   C   s    zQuaternion.ac                 C   s   | j S r1   )r&   r2   r   r   r   r,   G   s    zQuaternion.bc                 C   s   | j S r1   )r'   r2   r   r   r   r-   K   s    zQuaternion.cc                 C   s   | j S r1   )r(   r2   r   r   r   r.   O   s    zQuaternion.dc                 C   s   | j S r1   )r)   r2   r   r   r   r/   S   s    zQuaternion.real_fieldc                 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   Halfr   )r*   vectoranglexyznormsr+   r,   r-   r.   r   r   r   from_axis_angleW   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

              )r   r   )r>   r>   )r4   r4   r4   )r4   r>   )r>   r4   )r   r4   )r4   r   )r>   r   )r   r>   )detr   r
   r   r   )r*   MZabsQr+   r,   r-   r.   r   r   r   from_rotation_matrix   s    $$$$zQuaternion.from_rotation_matrixc                 C   s
   |  |S r1   addr3   otherr   r   r   __add__   s    zQuaternion.__add__c                 C   s
   |  |S r1   rC   rE   r   r   r   __radd__   s    zQuaternion.__radd__c                 C   s   |  |d S NrC   rE   r   r   r   __sub__   s    zQuaternion.__sub__c                 C   s   |  | t|S r1   _generic_mulr   rE   r   r   r   __mul__   s    zQuaternion.__mul__c                 C   s   |  t|| S r1   rL   rE   r   r   r   __rmul__   s    zQuaternion.__rmul__c                 C   s
   |  |S r1   )pow)r3   pr   r   r   __pow__   s    zQuaternion.__pow__c                 C   s   t | j | j | j | j S r1   )r   r%   r&   r'   r.   r2   r   r   r   __neg__   s    zQuaternion.__neg__c                 C   s   | t |d  S rI   r   rE   r   r   r   __truediv__   s    zQuaternion.__truediv__c                 C   s   t || d  S rI   rT   rE   r   r   r   __rtruediv__   s    zQuaternion.__rtruediv__c                 G   s
   | j | S r1   r   r3   argsr   r   r   _eval_Integral   s    zQuaternion._eval_Integralc                    s(     dd | j fdd| jD  S )NevaluateTc                    s   g | ]}|j i  qS r   )diff)r   r+   kwargssymbolsr   r   
<listcomp>   r    z#Quaternion.diff.<locals>.<listcomp>)
setdefaultfuncrX   )r3   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   r/   
is_complexr   r+   r   r,   r-   r.   r   r#   )r3   rF   q1q2r   r   r   rD      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

        rL   rE   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rt|| j || j || j	 || j
 S td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
  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.)rb   r   r/   rc   r   r   r   r+   r,   r-   r.   r#   )rd   re   r   r   r   rM   /  s&    +
&
&2.0.zQuaternion._generic_mulc                 C   s    | }t |j|j |j |j S )z(Returns the conjugate of the quaternion.)r   r+   r,   r-   r.   r3   qr   r   r   _eval_conjugatet  s    zQuaternion._eval_conjugatec                 C   s4   | }t t|jd |jd  |jd  |jd  S )z#Returns the norm of the quaternion.r4   )r
   r   r+   r,   r-   r.   rg   r   r   r   r;   y  s    zQuaternion.normc                 C   s   | }|d|    S )z.Returns the normalized form of the quaternion.r>   )r;   rg   r   r   r   	normalize  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 normr>   r4   )r;   r#   r   rg   r   r   r   inverse  s    zQuaternion.inversec                 C   st   t |}| }|dkr| S d}|js*tS |dk rB| |  }}|dkrp|d dkr^|| }|d }|| }qB|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

        rJ   r>   r   r4   )r   rk   
is_IntegerNotImplemented)r3   rQ   rh   resr   r   r   rP     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 (e^q).

        Returns
        =======

        Quaternion
            Exponential of q (e^q).

        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

        r4   )	r
   r,   r-   r.   r   r+   r   r   r   )r3   rh   vector_normr+   r,   r-   r.   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 )ae  Returns the natural logarithm of the quaternion (_ln(q)).

        Examples
        ========

        >>> from sympy import Quaternion
        >>> q = Quaternion(1, 2, 3, 4)
        >>> q._ln()
        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

        r4   )	r
   r,   r-   r.   r;   lnr   r+   r   )r3   rh   ro   Zq_normr+   r,   r-   r.   r   r   r   _ln  s    "zQuaternion._lnc                    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 ))n)evalf)r   argnprecr   r   r_     r    z*Quaternion._eval_evalf.<locals>.<listcomp>)r   r   rX   )r3   precr   ru   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;   )r3   rQ   rh   vr7   re   r   r   r   pow_cos_sin  s    zQuaternion.pow_cos_sinc                 G   sF   t t| jg|R  t| jg|R  t| jg|R  t| jg|R  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   r+   r,   r-   r.   rW   r   r   r   r   0  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   r>   r4   )	rb   tupler   r=   rj   r   r,   r-   r.   )Zpinrrh   Zpoutr   r   r   rotate_pointQ  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

        rJ   r4   r>   )	r+   is_negativerj   r   r   r
   r,   r-   r.   )	r3   rh   r7   r<   r8   r9   r:   rz   tr   r   r   ry   ~  s    
zQuaternion.to_axis_angleNc                 C   s  | }|  d }dd| |jd |jd    }d| |j|j |j|j   }d| |j|j |j|j   }d| |j|j |j|j   }dd| |jd |jd    }d| |j|j |j|j   }	d| |j|j |j|j   }
d| |j|j |j|j   }dd| |jd |jd    }|sVt|||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

        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.

        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((1, 1, 1)))
         Matrix([
        [cos(x), -sin(x), 0,  sin(x) - cos(x) + 1],
        [sin(x),  cos(x), 0, -sin(x) - cos(x) + 1],
        [     0,       0, 1,                    0],
        [     0,       0, 0,                    1]])

        r>   r4   r   N)r;   r-   r.   r,   r+   Matrix)r3   rz   rh   r<   Zm00Zm01Zm02Zm10Zm11Zm12Zm20Zm21Zm22r8   r9   r:   Zm03Zm13Zm23Zm30Zm31Zm32Zm33r   r   r   to_rotation_matrix  s,    1          
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

        )r+   r2   r   r   r   scalar_part  s    zQuaternion.scalar_partc                 C   s   t d| j| j| jS )a  
        Returns vector part($\mathbf{V}(q)$) 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   r,   r-   r.   r2   r   r   r   vector_part  s    zQuaternion.vector_partc                 C   s    |    }td|j|j|jS )a  
        Returns the axis($\mathbf{Ax}(q)$) of the quaternion.

        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   rj   r   r,   r-   r.   )r3   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

        )r+   is_zeror2   r   r   r   is_pure>  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   r2   r   r   r   is_zero_quaternionY  s    zQuaternion.is_zero_quaternionc                 C   s   t |   |  S )a  
        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::
            angle := atan2(\sqrt{b^2 + c^2 + d^2}, {a})

        Examples
        ========

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

        )r   r   r;   r   r2   r   r   r   r7   y  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)r   r#   r   r   rE   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#   r   r,   r-   r.   r@   r   )r*   rd   re   Zq3rA   r   r   r   vector_coplanar  s    3$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#   r   rE   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   rE   r   r   r   
orthogonal%  s    %zQuaternion.orthogonalc                 C   s   |   |   S )a  
        Returns the index vector of the quaternion.

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

        Index vector is given by $\mathbf{T}(q)$ multiplied by $\mathbf{Ax}(q)$ where $\mathbf{Ax}(q)$ is the axis of the quaternion q,
        and mod(q) is the $\mathbf{T}(q)$ (magnitude) of the quaternion.

        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   r2   r   r   r   index_vectorO  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

        )rp   r;   r2   r   r   r   mensorp  s    zQuaternion.mensor)r   r   r   r   T)N)8__name__
__module____qualname____doc___op_priorityr   r$   propertyr+   r,   r-   r.   r/   classmethodr=   rB   rG   rH   rK   rN   rO   rR   rS   rU   rV   rY   r[   rD   rf   staticmethodrM   ri   r;   rj   rk   rP   r   rq   rx   r{   r   r~   ry   r   r   r   r   r   r   r7   r   r   r   r   r   r   r   r   r   r   r      sx   






*
+6)
D.#!
,(
N /
8**!r   N)&sympy.core.numbersr   Zsympy.core.singletonr   $sympy.functions.elementary.complexesr   r   r   r   &sympy.functions.elementary.exponentialr   r	   rp   (sympy.functions.elementary.miscellaneousr
   (sympy.functions.elementary.trigonometricr   r   r   r   sympy.simplify.trigsimpr   sympy.integrals.integralsr   sympy.matrices.denser   r   sympy.core.sympifyr   r   sympy.core.exprr   Zsympy.core.logicr   r   mpmath.libmp.libmpfr   r   r   r   r   r   <module>   s   