� ��g�����ddlmZddlmZddlmZddlmZmZm Z m Z ddl m Z m ZddlmZddlmZmZmZddlmZmZdd lmZdd lmZdd lmZdd lmZm Z dd l!m"Z"ddl#m$Z$m%Z%ddl&m'Z'ddl(m)Z)d�Z*d�Z+Gd�de"��Z,dS)�)�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��|�u|jrp|jdurtd���td�|D����}|r?t |dzt d�|D������durtd���dSdSdSdS)z$validate if input norm is consistentNFzInput norm must be positive.c3�6K�|]}|jo|jduV��dS)TN)� is_number�is_real��.0�is �i/home/asafur/pinokio/api/open-webui.git/app/env/lib/python3.11/site-packages/sympy/algebras/quaternion.py� <genexpr>z_check_norm.<locals>.<genexpr>s0����L�L�a�� �9�� �T�(9�L�L�L�L�L�L��c3� K�|] }|dzV�� dS)r'N�r!s r$r%z_check_norm.<locals>.<genexpr>s&����+C�+C�Q�A�q�D�+C�+C�+C�+C�+C�+Cr&zIncompatible value for norm.)r� is_positive� ValueError�allr�sum)�elements�norm� numericals r$� _check_normr1s��� ��D�N�� � �u� $� $��;�<�<� <��L�L�8�L�L�L�L�L� � � =��t�Q�w��+C�+C�(�+C�+C�+C�(C�(C�D�D��M�M��;�<�<� <� ����  =� =�M�Mr&c�F�t|��tkrtd���t|��dkr"td�|�����|���}|���}|s|std���|���\}}}||ks||krtd���t|��td��z }|r5td�d� |�������|S) zGvalidate seq and return True if seq is lowercase and False if uppercasezExpected seq to be a string.�zExpected 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_extrinsicrEs�� �C�y�y�C����7�8�8�8� �3�x�x�1�}�}��5�<�<�S�A�A�B�B�B�� � � � �I�� � � � �I� �(��(��'�(�(� (��i�i�k�k�G�A�q�!� �Q���A��F�F��=�>�>�>� �c�(�(�S��]�]� "�C� �8��"�"(�&�������"6�"6�8�8� 8� �r&c�V��eZdZdZdZdZd>�fd� Zd�Zed ���Z ed ���Z ed ���Z ed ���Z ed ���Z ed���Zed���Zd?d�Zed���Zed���Zd@d�Zed���Zed���Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�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/���Z1d0�Z2dAd1�Z3d2�Z4d3�Z5d4�Z6d5�Z7d6�Z8d7�Z9d8�Z:ed9���Z;d:�Z<d;�Z=d<�Z>d=�Z?�xZ@S)B� 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&@FrTNc���tt||||f��\}}}}td�||||fD����rtd���t ���|||||��}||_|�|��|S)Nc3�(K�|] }|jduV��dS)FN)�is_commutativer!s r$r%z%Quaternion.__new__.<locals>.<genexpr>rs*����?�?�Q�q��5�(�?�?�?�?�?�?r&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$rNzQuaternion.__new__os������1�a��A�,�/�/� ��1�a�� �?�?�1�a��A�,�?�?�?� ?� ?� A��?�@�@� @��g�g�o�o�c�1�a��A�.�.��$��� � � �T����� r&c�\�t|��}t|j|��||_dS)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)rr1�args�_norm)�selfr/s r$rPzQuaternion.set_normys-��@�t�}�}���D�I�t�$�$�$��� � � r&c��|jdS)Nr�rZ�r\s r$rRz Quaternion.a�����y��|�r&c��|jdS)N�r^r_s r$rSz Quaternion.b�r`r&c��|jdS)Nr'r^r_s r$rTz Quaternion.c�r`r&c��|jdS)Nr3r^r_s r$rUz Quaternion.d�r`r&c��|jS�N)rOr_s r$rVzQuaternion.real_field�s ����r&c ���t|j|j |j |j g|j|j|j |jg|j|j|j|j g|j|j |j|jgg��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]]) ��MatrixrRrSrTrUr_s r$�product_matrix_leftzQuaternion.product_matrix_left�sx��X���$�&��4�6�'�D�F�7�3�����$�&��$�&�1�������$�&��1���$�&��$�&�$�&�1� 3�4�4� 4r&c ���t|j|j |j |j g|j|j|j|j g|j|j |j|jg|j|j|j |jgg��S)aMReturns 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]]) rhr_s r$�product_matrix_rightzQuaternion.product_matrix_right�sx��b���$�&��4�6�'�D�F�7�3�������$�&��1���$�&��$�&�$�&�1�����$�&��$�&�1� 3�4�4� 4r&c�f�|rt|jdd���St|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]]) rbN)rirZ)r\� vector_onlys r$� to_MatrixzQuaternion.to_Matrixs5��X � %��$�)�A�B�B�-�(�(� (��$�)�$�$� $r&c��t|��}|dkr(|dkr"td�|�����|dkr tdg|�R�St|�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)r8r+r9rG)rQr.�lengths r$� from_MatrixzQuaternion.from_MatrixKso��B�X���� �Q�;�;�6�Q�;�;��(�(.��v���8�8� 8� �Q�;�;��a�+�(�+�+�+� +��x�(� (r&c��� � � �t|��dkrtd���t|��}|���\� � � � fd�dD��}� fd�dD��}� fd�dD��}|�||d��}|�||d��}|�||d ��} |rt | |z|z��St ||z| z��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 r3z3 angles must be given.c�$��g|] }|�krdnd�� S�rbrr))r"�nr#s �r$� <listcomp>z)Quaternion.from_euler.<locals>.<listcomp>��%��� 0� 0� 0�Q�1��6�6�a�a�q� 0� 0� 0r&�xyzc�$��g|] }|�krdnd�� Srvr))r"rwrBs �r$rxz)Quaternion.from_euler.<locals>.<listcomp>�ryr&c�$��g|] }|�krdnd�� Srvr))r"rwrCs �r$rxz)Quaternion.from_euler.<locals>.<listcomp>�ryr&rrbr')r8r+rEr<�from_axis_angler) rQ�anglesr?rA�ei�ej�ek�qi�qj�qkr#rBrCs @@@r$� from_eulerzQuaternion.from_eulervs�����V �v�;�;�!� � ��6�7�7� 7�!�#�&�&� ��)�)�+�+���1�a�1� 0� 0� 0�%� 0� 0� 0�� 0� 0� 0� 0�%� 0� 0� 0�� 0� 0� 0� 0�%� 0� 0� 0��� � ��V�A�Y� /� /�� � � ��V�A�Y� /� /�� � � ��V�A�Y� /� /�� � *��B��G�b�L�)�)� )��B��G�b�L�)�)� )r&c �V�|���rtd���gd�}t|��}|���\}}}d�|��dz}d�|��dz}d�|��dz}|s||}}||k} | rd|z |z }||z ||z z||z zdz} |j|j|j|jg} | d} | |} | |}| || z}| s| |z | |z|| z|| z f\} } }}|r�| rB|� ��dz}t| | z| | zz||zz ||zz |z ��|d<n�d|� ��dzz}t||z||zz| | zz | | zz |z ��|d<nadtt||z||zz��t| | z| | zz����z|d<| s|dxxtjdz zcc<d}t!|tj��rt!|tj��rd}t!| tj��rt!| tj��rd}|dkr�|rIt| | ��t||��z|d<t| | ��t||��z |d<n�t| |z| |zz| |z| |zz ��|d<t| |z| |zz | |z| |zz��|d<nctj|d| z<|dkrdt| | ��z|d|z<n0dt||��z|d|z<|d|zxx|rdndzcc<| s|dxx| zcc<|rt%|d d d���St%|��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.)rrrrzrb�r'r�����N)�is_zero_quaternionr+rEr<�indexrRrSrTrUr/r rrr r�Pir�Zero�tuple)r\r?�angle_addition�avoid_square_rootr~rAr#rBrC� symmetricr r.rRrSrTrU�n2�cases r$�to_eulerzQuaternion.to_euler�s*��@ � "� "� $� $� I��G�H�H� H�����!�#�&�&� ��)�)�+�+���1�a� �K�K��N�N�Q� �� �K�K��N�N�Q� �� �K�K��N�N�Q� ��� ��a�q�A���F� � � ��A��� �A��A��!�a�%� �A��E�*�a�/���F�D�F�D�F�D�F�3�� �Q�K�� �Q�K�� �Q�K�� �Q�K�$� ��� 4��Q���A��q�1�u�a�!�e�3�J�A�q�!�Q� � &�� G��Y�Y�[�[�!�^�� �!�a�%�!�a�%�-�!�a�%�"7�!�a�%�"?�2�!E�F�F��q� � �������a��'�� �!�a�%�!�a�%�-�!�a�%�"7�!�a�%�"?�2�!E�F�F��q� � ��E�$�q�1�u�q�1�u�}�"5�"5�t�A��E�A��E�M�7J�7J�K�K�K�F�1�I�� &��q� � � �Q�T�A�X�%� � � ��� ��A�F� � � ��a��� 0� 0� ��D� ��A�F� � � ��a��� 0� 0� ��D� �1�9�9�� 8�!�!�Q�K�K�%��1�+�+�5��q� �!�!�Q�K�K�%��1�+�+�5��q� � �!�!�A�#��!��)�Q�q�S�1�Q�3�Y�7�7��q� �!�!�A�#��!��)�Q�q�S�1�Q�3�Y�7�7��q� � �+,�&�F�1�I� �&� '��q�y�y�()�E�!�Q�K�K���q�9�}�%�%�()�E�!�Q�K�K���q�9�}�%��q�9�}�%�%�%� �*@�"�"�q�A�%�%�%�� � �1�I�I�I�� �I�I�I� � !�����"���&�&� &���=�=� r&c��|\}}}t|dz|dzz|dzz��}||z ||z ||z }}}t|tjz��}t |tjz��}||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 rr�Halfr) rQ�vector�angle�x�y�zr/�srRrSrTrUs r$r}zQuaternion.from_axis_angleDs���8� ��A�q��A�q�D�1�a�4�K�!�Q�$�&�'�'����X�q�4�x��T��q�A�� ����� � �� ����� � �� ��E�� ��E�� ��E�� �s�1�a��A���r&c��|���tdd��z}t||dz|dz|dz��dz }t||dz|dz |dz ��dz }t||dz |dz|dz ��dz }t||dz |dz |dz��dz }|t|d|dz ��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 rbr3)rr)rbrb)r'r'r')r'rb)rbr')rr')r'rrv)rrb)�detrr r rG)rQ�M�absQrRrSrTrUs r$�from_rotation_matrixzQuaternion.from_rotation_matrixos?��>�u�u�w�w���A���&�� ���$���!�D�'�)�A�d�G�3� 4� 4�q� 8�� ���$���!�D�'�)�A�d�G�3� 4� 4�q� 8�� ���$���!�D�'�)�A�d�G�3� 4� 4�q� 8�� ���$���!�D�'�)�A�d�G�3� 4� 4�q� 8�� ��Q�t�W�q��w�&�'�'� '�� ��Q�t�W�q��w�&�'�'� '�� ��Q�t�W�q��w�&�'�'� '���!�Q��1�%�%�%r&c�,�|�|��Srf��add�r\�others r$�__add__zQuaternion.__add__�����x�x����r&c�,�|�|��Srfr�r�s r$�__radd__zQuaternion.__radd__�r�r&c�2�|�|dz��S�Nr�r�r�s r$�__sub__zQuaternion.__sub__�s���x�x��b��!�!�!r&c�H�|�|t|����Srf�� _generic_mulrr�s r$�__mul__zQuaternion.__mul__�s��� � ��x����7�7�7r&c�H�|�t|��|��Srfr�r�s r$�__rmul__zQuaternion.__rmul__�s��� � ��%���$�7�7�7r&c�,�|�|��Srf)�pow)r\�ps r$�__pow__zQuaternion.__pow__�s���x�x��{�{�r&c�V�t|j |j |j |j ��Srf)rGrRrSrTrUr_s r$�__neg__zQuaternion.__neg__�s&���4�6�'�D�F�7�T�V�G�d�f�W�=�=�=r&c�,�|t|��dzzSr��rr�s r$� __truediv__zQuaternion.__truediv__�s���g�e�n�n�b�(�(�(r&c�,�t|��|dzzSr�r�r�s r$� __rtruediv__zQuaternion.__rtruediv__�s���u�~�~��b��(�(r&c��|j|�Srfr�r\rZs r$�_eval_IntegralzQuaternion._eval_Integral�s���t�~�t�$�$r&c�j�����dd��|j��fd�|jD���S)N�evaluateTc�*��g|]}|j�i�����Sr))�diff)r"rR�kwargs�symbolss ��r$rxz#Quaternion.diff.<locals>.<listcomp>�s*���J�J�J�!�6�1�6�7�5�f�5�5�J�J�Jr&)� setdefault�funcrZ)r\r�r�s ``r$r�zQuaternion.diff�sC�������*�d�+�+�+��t�y�J�J�J�J�J�� �J�J�J�K�Kr&c��|}t|��}t|t��s�|jrM|jrFtt |��|jzt|��|jz|j |j ��S|j r)t|j|z|j|j |j ��Std���t|j|jz|j|jz|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� isinstancerGrV� is_complexrrRrrSrTrUrJr+)r\r��q1�q2s r$r�zQuaternion.add�s���N�� �U�^�^���"�j�)�)� a��}� a��� a�!�"�R�&�&�2�4�-��B���"�$����b�d�K�K�K��"� a�!�"�$��)�R�T�2�4���>�>�>� �!_�`�`�`��"�$���+�r�t�b�d�{�B�D�2�4�K����D�B!�"�"� "r&c�H�|�|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$�mulzQuaternion.mul�s!��N� � ��x����7�7�7r&c�P�t|t��st|t��s||zSt|t��s�|jr6|jr/tt |��t |��dd��|zS|jr2t||jz||jz||j z||j z��Std���t|t��s�|jr6|jr/|tt |��t |��dd��zS|jr2t||jz||jz||j z||j z��Std���|j � |j �d}n)|� ��|� ��z}t|j |jz|j |j zz |j |j zz |j|jzz|j|jz|j |j zz|j |j zz |j|jzz|j |j z|j |jzz|j |jzz|j|j zz|j|j z|j |jzz |j |jzz|j|j zz|���S)anGeneric 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 rzAOnly commutative expressions can be multiplied with a Quaternion.N�r/)r�rGrVr�rrrJrRrSrTrUr+r[r/)r�r�r/s r$r�zQuaternion._generic_mulst��V�"�j�)�)� �*�R��2L�2L� ���7�N��"�j�)�)� f��}� f��� f�!�"�R�&�&�"�R�&�&�!�Q�7�7�"�<�<��"� f�!�"�r�t�)�R�"�$�Y��R�T� �2���9�M�M�M� �!d�e�e�e��"�j�)�)� f��}� f��� f��J�r�"�v�v�r�"�v�v�q�!�<�<�<�<��"� f�!�"�r�t�)�R�"�$�Y��R�T� �2���9�M�M�M� �!d�e�e�e� �8� ��� 0��D�D��7�7�9�9�r�w�w�y�y�(�D��2�4�%���*�r�t�B�D�y�0�2�4���9�<�r�t�B�D�y�H��$�r�t�)�b�d�2�4�i�/�"�$�r�t�)�;�b�d�2�4�i�G��4�%���*�r�t�B�D�y�0�2�4���9�<�r�t�B�D�y�H��$�r�t�)�b�d�2�4�i�/�"�$�r�t�)�;�b�d�R�T�k�I�#� %�%�%� %r&c�f�|}t|j|j |j |j |j���S)z(Returns the conjugate of the quaternion.r�)rGrRrSrTrUr[�r\�qs r$�_eval_conjugatezQuaternion._eval_conjugatehs0�� ���!�#���t�a�c�T�A�C�4�a�g�>�>�>�>r&c��|j�G|}tt|jdz|jdzz|jdzz|jdzz����S|jS)z#Returns the norm of the quaternion.Nr')r[r rrRrSrTrUr�s r$r/zQuaternion.normmsU�� �:� ��A�����a��!�#�q�&��1�3��6�!9�A�C��F�!B�C�C�D�D� D��z�r&c�:�|}|d|���z zS)z.Returns the normalized form of the quaternion.rbr�r�s r$� normalizezQuaternion.normalizews�� ���A�a�f�f�h�h�J��r&c��|}|���std���t|��d|���dzz zS)z&Returns the inverse of the quaternion.z6Cannot compute inverse for a quaternion with zero normrbr')r/r+rr�s r$�inversezQuaternion.inverse|sH�� ���v�v�x�x� W��U�V�V� V���|�|�q������1��}�-�-r&c�� |t|��}}n#t$r tcYSwxYw|dkr|���| }}|dkr|St dddd��}|dkr|dzr||z}||z}|dz}|dk�|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 rrb)rr+�NotImplementedr�rG)r\r�r��ress r$r�zQuaternion.pow�s���2 "������q�A�A��� "� "� "�!� !� !� !� "���� �q�5�5��9�9�;�;���q�A� ��6�6��H���A�q�!�$�$���!�e�e��1�u� ��q��� ��F�A� �!�G�A� �!�e�e� � s ��(�(c���|}t|jdz|jdzz|jdzz��}t |j��t |��z}t |j��t|��z|jz|z }t |j��t|��z|jz|z }t |j��t|��z|jz|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 rSrTrUr rRrrrG)r\r�� vector_normrRrSrTrUs r$r zQuaternion.exp�s���, ���1�3��6�A�C��F�?�Q�S�!�V�3�4�4� � ���H�H�s�;�'�'� '�� ���H�H�s�;�'�'� '�!�#� -� � ;�� ���H�H�s�;�'�'� '�!�#� -� � ;�� ���H�H�s�;�'�'� '�!�#� -� � ;���!�Q��1�%�%�%r&c��|}t|jdz|jdzz|jdzz��}|���}t |��}|jt |j|z ��z|z }|jt |j|z ��z|z }|jt |j|z ��z|z }t||||��S)agReturns 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 rSrTrUr/�lnr rRrG)r\r�r��q_normrRrSrTrUs r$r zQuaternion.log�s��� ���1�3��6�A�C��F�?�Q�S�!�V�3�4�4� ������� �v�J�J�� �C�$�q�s�V�|�$�$� $�{� 2�� �C�$�q�s�V�|�$�$� $�{� 2�� �C�$�q�s�V�|�$�$� $�{� 2���!�Q��1�%�%�%r&c����fd�|jD��}|j}|� |j��}t||��t |d|i�S)Nc�$��g|] }|j���� Sr))�subs)r"r#rZs �r$rxz)Quaternion._eval_subs.<locals>.<listcomp>�s!���5�5�5�a�F�A�F�D�M�5�5�5r&r/)rZr[r�r1rG)r\rZr.r/s ` r$� _eval_subszQuaternion._eval_subs�s\���5�5�5�5�4�9�5�5�5���z�� � ��4�9�d�#�D��H�d�#�#�#��8�/�$�/�/�/r&c�V��t|���t�fd�|jD���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�<��g|]}|�������S))rw)�evalf)r"�arg�nprecs �r$rxz*Quaternion._eval_evalf.<locals>.<listcomp>s'���D�D�D�3�C�I�I��I�.�.�D�D�Dr&)rrGrZ)r\�precr�s @r$� _eval_evalfzQuaternion._eval_evalf�s4���,�D�!�!���D�D�D�D�$�)�D�D�D�E�Er&c��|}|���\}}t�|||z��}||���|zzS)aYComputes 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_anglerGr}r/)r\r�r��vr�r�s r$� pow_cos_sinzQuaternion.pow_cos_sin sL��< ���_�_�&�&� ��E� � '� '��1�u�9� 5� 5���Q�V�V�X�X�q�[�!�!r&c ��tt|jg|�R�t|jg|�R�t|jg|�R�t|jg|�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 )rGrrRrSrTrUr�s r$rzQuaternion.integrate-sj��<�)�D�F�2�T�2�2�2�I�d�f�4L�t�4L�4L�4L�#�D�F�2�T�2�2�2�I�d�f�4L�t�4L�4L�4L�N�N� Nr&c�:�t|t��r(t�|d|d��}n|���}|td|d|d|d��zt |��z}|j|j|jfS)aReturns 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) rrbr') r�r�rGr}r�rrSrTrU)�pin�rr��pouts r$� rotate_pointzQuaternion.rotate_pointNs���H �a�� � � ��*�*�1�Q�4��1��6�6�A�A�� � � � �A��:�a��Q���Q���Q��8�8�8�9�Q�<�<�G��������'�'r&c�v�|}|jjr|dz}|���}tdt |j��z��}t d|j|jzz ��}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�rr r rSrTrU) r\r�r�r�r�r�r�r��ts r$r�zQuaternion.to_axis_angle{s���* �� �3�?� ��B��A� �K�K�M�M����T�!�#�Y�Y��'�'�� ��Q�S���W�� � �� �Q�S�1�W� � �� �Q�S�1�W� � �� �Q�S�1�W� � �� ��1�I�� ��J���r&c ���|}|���dz}|r�||jdz|jdzz|jdzz |jdzz z}||jdz|jdzz |jdzz|jdzz z}||jdz|jdzz |jdzz |jdzzz}nZdd|z|jdz|jdzzzz }dd|z|jdz|jdzzzz }dd|z|jdz|jdzzzz }d|z|j|jz|j|jzz z}d|z|j|jz|j|jzzz} d|z|j|jz|j|jzzz} d|z|j|jz|j|jzz z} d|z|j|jz|j|jzz z} d|z|j|jz|j|jzzz} |st ||| g| || g| | |gg��S|\}}}|||zz ||zz || zz }||| zz ||zz || zz }||| zz || zz ||zz }dx}x}}d}t ||| |g| || |g| | ||g||||gg��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'rbr)r/rRrSrTrUri)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_matrixzQuaternion.to_rotation_matrix�s���N �� �F�F�H�H�b�L�� � ,��Q�S�!�V�a�c�1�f�_�q�s�A�v�-���Q��6�7�C��Q�S�!�V�a�c�1�f�_�q�s�A�v�-���Q��6�7�C��Q�S�!�V�a�c�1�f�_�q�s�A�v�-���Q��6�7�C�C��a��c�1�3��6�A�C��F�?�+�+�C��a��c�1�3��6�A�C��F�?�+�+�C��a��c�1�3��6�A�C��F�?�+�+�C���c�1�3�q�s�7�Q�S���W�$�%����c�1�3�q�s�7�Q�S���W�$�%����c�1�3�q�s�7�Q�S���W�$�%����c�1�3�q�s�7�Q�S���W�$�%����c�1�3�q�s�7�Q�S���W�$�%����c�1�3�q�s�7�Q�S���W�$�%��� G��C��c�?�S�#�s�O�c�3��_�M�N�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� Gr&c��|jS)amReturns 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 )rRr_s r$� scalar_partzQuaternion.scalar_part�s ��$�v� r&c�D�td|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)rGrSrTrUr_s r$� vector_partzQuaternion.vector_parts��.�!�T�V�T�V�T�V�4�4�4r&c��|������}td|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)rr�rGrSrTrU)r\�axiss r$rzQuaternion.axiss;��2���!�!�+�+�-�-���!�T�V�T�V�T�V�4�4�4r&c��|jjS)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_purezQuaternion.is_pure9s��2�v�~�r&c�4�|���jS)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/rr_s r$r�zQuaternion.is_zero_quaternionTs��<�y�y�{�{�"�"r&c��dt|������|�����zS)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')rrr/rr_s r$r�zQuaternion.anglets=��.�5��)�)�+�+�0�0�2�2�D�4D�4D�4F�4F�G�G�G�Gr&c�v�|���s|���rtd���t|���|���z ���|���|���z���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+rrr�s r$� arc_coplanarzQuaternion.arc_coplanar�s���T � #� #� %� %� J�5�+C�+C�+E�+E� J��H�I�I� I��$�)�)�+�+�� � � � �4�H�H�J�J�T�Y�Y�[�[�[`�[e�[e�[g�[g�Mg�L{�L{�L}�L}�~���r&c��t|�����sBt|�����s!t|�����rtd���t|j|j|jg|j|j|jg|j|j|jgg�����}|jS)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) rrr+rirSrTrUr�r)rQr�r��q3r�s r$�vector_coplanarzQuaternion.vector_coplanar�s���l �R�Z�Z�\�\� "� "� C�i�� � � � �&=�&=� C��2�:�:�<�<�AX�AX� C��A�B�B� B� �R�T�2�4���&���r�t�R�T�(:�R�T�2�4���<N�O� P� P� T� T� V� V���y�r&c���t|�����s!t|�����rtd���||z||zz ���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�rrr+r�r�s r$�parallelzQuaternion.parallel�sd��J �T�\�\�^�^� $� $� F� �%�-�-�/�/�(B�(B� F��D�E�E� E��U� �U�4�Z�'�;�;�=�=�=r&c���t|�����s!t|�����rtd���||z||zz���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 rr!r�s r$� orthogonalzQuaternion.orthogonal#sd��J �T�\�\�^�^� $� $� C� �%�-�-�/�/�(B�(B� C��A�B�B� B��U� �U�4�Z�'�;�;�=�=�=r&c�T�|���|���zS)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/rr_s r$� index_vectorzQuaternion.index_vectorMs��>�y�y�{�{�T�Y�Y�[�[�(�(r&c�D�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/r_s r$�mensorzQuaternion.mensorns��*�$�)�)�+�+���r&)rrrrTN)F)TF)NT)A�__name__� __module__� __qualname__�__doc__� _op_priorityrJrNrP�propertyrRrSrTrUrVrjrlro� classmethodrsr�r�r}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�rr�r�rrrrrr�r�rrr"r$r&r(� __classcell__)rXs@r$rGrG:sk�������/�/�`�L��N�������"�"�"�H����X������X������X������X��� � ��X� ��/4�/4��X�/4�b�44�44��X�44�l/%�/%�/%�/%�b�()�()��[�()�T�=*�=*��[�=*�~L!�L!�L!�L!�\�(�(��[�(�T�)&�)&��[�)&�V������"�"�"�8�8�8�8�8�8����>�>�>�)�)�)�)�)�)�%�%�%�L�L�L�4"�4"�4"�l'8�'8�'8�R�I%�I%��\�I%�V?�?�?� ��� � � � .�.�.�+�+�+�Z&�&�&�>&�&�&�40�0�0�F�F�F�2!"�!"�!"�FN�N�N�B�*(�*(��\�*(�X&�&�&�PJG�JG�JG�JG�X���(5�5�5�25�5�5�:���6#�#�#�@H�H�H�4-@�-@�-@�^�9�9��[�9�v(>�(>�(>�T(>�(>�(>�T)�)�)�B������r&rGN)-�sympy.core.numbersr�sympy.core.singletonr�sympy.core.relationalr�$sympy.functions.elementary.complexesrrrr �&sympy.functions.elementary.exponentialr r r��(sympy.functions.elementary.miscellaneousr �(sympy.functions.elementary.trigonometricr rrrr�sympy.simplify.trigsimpr�sympy.integrals.integralsr�sympy.matrices.denserri�sympy.core.sympifyrr�sympy.core.exprr�sympy.core.logicrr�sympy.utilities.miscr�mpmath.libmp.libmpfrr1rErGr)r&r$�<module>rAs���'�'�'�'�'�'�"�"�"�"�"�"�'�'�'�'�'�'�J�J�J�J�J�J�J�J�J�J�J�J�C�C�C�C�C�C�C�C�9�9�9�9�9�9�H�H�H�H�H�H�H�H�H�H�?�?�?�?�?�?�?�?�,�,�,�,�,�,�/�/�/�/�/�/�=�=�=�=�=�=�0�0�0�0�0�0�0�0� � � � � � �0�0�0�0�0�0�0�0�'�'�'�'�'�'�+�+�+�+�+�+�=�=�=����6I�I�I�I�I��I�I�I�I�Ir&
Memory