K i{ 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)dZ*dZ+Gdde"Z,y))Rational)S)is_eq) conjugateimresign)explog)sqrt)acosasinatan2)cossin)trigsimp integrate)MutableDenseMatrix)sympify_sympify)Expr) fuzzy_notfuzzy_or)as_int) prec_to_dpsc|h|jr[|jdur tdtd|D}|r-t |dzt d|Ddur tdyyyy)z$validate if input norm is consistentNFzInput norm must be positive.c3TK|] }|jxr|jdu"yw)TN) is_numberis_real.0is _/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/sympy/algebras/quaternion.py z_check_norm..s%La 9 T(99Ls&(c3&K|] }|dz yw)r&Nr!s r$r%z_check_norm..s+CQAqD+CszIncompatible value for norm.)r is_positive ValueErrorallrsum)elementsnorm numericals r$ _check_normr0st DNN   u $;< <L8LL tQw+C(+C(CDM;< <N9 +ct|tk7r tdt|dk7rtdj ||j }|j }|s |s td|j\}}}||k(s||k(r tdt|tdz }|r)tdj dj||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 differentxyzXYZzNExpected axes from `seq` to be from ['x', 'y', 'z'] or ['X', 'Y', 'Z'], got {}) typestrr*lenformatisupperislowerlowersetjoin)seq intrinsic extrinsicr#jkbads r$ _is_extrinsicrEs CyC788 3x1}5<> c(S] "C ""(&"68 8 r1ceZdZdZdZdZd;fd ZdZedZ edZ edZ ed Z ed Z ed Zed Zdd.Z3d/Z4d0Z5d1Z6d2Z7d3Z8d4Z9d5Z:ed6Z;d7Zd:Z?xZ@S)? QuaternionaProvides 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&@Fctt||||f\}}}}td||||fDr tdt||||||}||_|j||S)Nc38K|]}|jduyw)FN)is_commutativer!s r$r%z%Quaternion.__new__..rs?Qq5(?sz arguments have to be commutative)mapranyr*super__new__ _real_fieldset_norm) clsabcd real_fieldr.obj __class__s r$rNzQuaternion.__new__oso1aA,/ 1a ?1aA,? ??@ @goc1aA.$ T r1cTt|}t|j|||_y)aSets 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)rr0args_norm)selfr.s r$rPzQuaternion.set_normys#@t}DIIt$ r1c |jdS)NrrZr\s r$rRz Quaternion.ayy|r1c |jdS)Nr^r_s r$rSz Quaternion.br`r1c |jdS)Nr&r^r_s r$rTz Quaternion.cr`r1c |jdS)Nr3r^r_s r$rUz Quaternion.dr`r1c|jSN)rOr_s r$rVzQuaternion.real_fieldsr1c t|j|j |j |j g|j|j|j |jg|j|j|j|j g|j|j |j|jggS)aReturns 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_leftsX$&&466'DFF73$&&$&&1$&&1$&&$&&$&&1 34 4r1c t|j|j |j |j g|j|j|j|j g|j|j |j|jg|j|j|j |jggS)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_rightsb$&&466'DFF73$&&1$&&$&&$&&1$&&$&&1 34 4r1c`|rt|jddSt|jS)aReturns 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_Matrixs,X $))AB-( ($))$ $r1ct|}|dk7r|dk7rtdj||dk(r tdg|St|S)aReturns 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 r3z7Input elements must have length 3 or 4, got {} elementsr)r8r*r9rG)rQr-lengths r$ from_MatrixzQuaternion.from_MatrixKsZBX Q;6Q;((.v8 8 Q;a+(+ +x( (r1ct|dk7r tdt|}|j\}}}dDcgc] }||k(rdnd }}dDcgc] }||k(rdnd } }dDcgc] }||k(rdnd } }|j ||d} |j | |d} |j | |d} |rt | | z| zSt | | z| zScc}wcc}wcc}w)aReturns 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.xyzrbrr&)r8r*rEr<from_axis_angler)rQanglesr?rAr#rBrCneiejekqiqjqks r$ from_eulerzQuaternion.from_eulervs V v;! 67 7!#& ))+1a+0 0Q16aq 0 0*/ 0Q16aq 0 0*/ 0Q16aq 0 0 VAY /  VAY /  VAY / BGbL) )BGbL) )1 0 0sCC#)C(c |jr tdgd}t|}|j\}}}dj |dz}dj |dz}dj |dz}|s||}}||k(} | rd|z |z }||z ||z z||z zdz} |j |j |j|jg} | d} | |} | |}| || z}| s| |z | |z|| z|| z f\} } }}|ry| r:|jdz}t| | z| | zz||zz ||zz |z |d<nd|jdzz}t||z||zz| | zz | | zz |z |d<nVdtt||z||zzt| | z| | zzz|d<| s|dxxtjdz zcc<d}t!|tj"rt!|tj"rd}t!| tj"rt!| tj"rd}|dk(r~|r9t| | t||z|d<t| | t||z |d<nt| |z| |zz| |z| |zz |d<t| |z| |zz | |z| |zz|d<n[tj"|d| z<|dk(rdt| | z|d|z<n)dt||z|d|z<|d|zxx|rdndzcc<| s |dxx| zcc<|rt%|d d dSt%|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.)rrrrurbr&rN)is_zero_quaternionr*rEr<indexrRrSrTrUr.r rrr rPirZerotuple)r\r?angle_additionavoid_square_rootrwrAr#rBrC symmetricr r-rRrSrTrUn2cases r$to_eulerzQuaternion.to_eulersy@  " " $GH H!#& ))+1a KKNQ  KKNQ  KKNQ aqAF A AA!a% AE*a/FFDFFDFFDFF3 QK QK QK QK$ QAq1ua!e3JAq!Q YY[!^ !a%!a%-!a%"7!a%"?2!EFq a' !a%!a%-!a%"7!a%"?2!EFq E$q1uq1u}"5tAEAEM7JKKF1Iq QTTAX%  AFF a 0D AFF a 0D 19!!QK%1+5q !!QK%1+5q !!A#!)QqS1Q3Y7q !!A#!)QqS1Q3Y7q +,&&F1I & 'qy()E!QKq9}%()E!QKq9}%q9}% "qA% 1I I "& &= r1c|\}}}t|dz|dzz|dzz}||z ||z ||z }}}t|tjz}t |tjz}||z} ||z} ||z} ||| | | S)aReturns 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 rrHalfr) rQvectoranglexyzr.srRrSrTrUs r$rvzQuaternion.from_axis_angleDs8 AqAqD1a4K!Q$&'Xq4xTqA     E E E 1aAr1c|jtddz}t||dz|dz|dzdz }t||dz|dz |dz dz }t||dz |dz|dz dz }t||dz |dz |dzdz }|t|d|dz z}|t|d |d z z}|t|d |d z z}t ||||S) aReturns 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&r)rbr)rrb)detrr r rG)rQMabsQrRrSrTrUs r$from_rotation_matrixzQuaternion.from_rotation_matrixos#>uuwA& $!D')AdG3 4q 8 $!D')AdG3 4q 8 $!D')AdG3 4q 8 $!D')AdG3 4q 8 QtWqw&' ' QtWqw&' ' QtWqw&' '!Q1%%r1c$|j|Srfaddr\others r$__add__zQuaternion.__add__xxr1c$|j|Srfrrs r$__radd__zQuaternion.__radd__rr1c*|j|dzSNrrrs r$__sub__zQuaternion.__sub__sxxb!!r1c8|j|t|Srf _generic_mulrrs r$__mul__zQuaternion.__mul__s  x77r1c8|jt||Srfrrs r$__rmul__zQuaternion.__rmul__s  %$77r1c$|j|Srf)pow)r\ps r$__pow__zQuaternion.__pow__sxx{r1cvt|j |j |j |j Srf)rGrRrSrTrUr_s r$__neg__zQuaternion.__neg__s+466'DFF7TVVGdffW==r1c$|t|dzzSrrrs r$ __truediv__zQuaternion.__truediv__sgenb(((r1c$t||dzzSrrrs r$ __rtruediv__zQuaternion.__rtruediv__su~b((r1c |j|Srfrr\rZs r$_eval_IntegralzQuaternion._eval_Integralst~~t$$r1c |jdd|j|jDcgc]}|j|i|c}Scc}w)NevaluateT) setdefaultfuncrZdiff)r\symbolskwargsrRs r$rzQuaternion.diffsE*d+tyy J!616675f5JKKJsA c||}t|}t|ts|jrZ|jrNtt ||j zt||jz|j|jS|jr9t|j |z|j|j|jStdt|j |j z|j|jz|j|jz|j|jzS)aAdds 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> !_``"$$+rttbdd{BDD244KDDB!" "r1c8|j|t|S)aMultiplies 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 rrs r$mulzQuaternion.mulsN  x77r1ct|tst|ts||zSt|ts|jr/|jr#tt |t |dd|zS|j rBt||jz||jz||jz||jzStdt|ts|jr/|jr#|tt |t |ddzS|j rBt||jz||jz||jz||jzStd|j|jd}n!|j|jz}t|j |jz|j|jzz |j|jzz |j|jzz|j|jz|j|jzz|j|jzz |j|jzz|j |jz|j|jzz|j|jzz|j|jzz|j|jz|j|jzz |j|jzz|j|jzz|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.Nr.)rrGrVrrrrJrRrSrTrUr*r[r.)rrr.s r$rzQuaternion._generic_mulsfV"j)*R2L7N"j)}}!"R&"R&!Q7"<<""!"rtt)R"$$YRTT 29MM !dee"j)}}Jr"vr"vq!<<<""!"rtt)R"$$YRTT 29MM !dee 88  0D779rwwy(D244%*rttBDDy02449>r1c|jS|}tt|jdz|jdzz|j dzz|j dzzS|jS)z#Returns the norm of the quaternion.r&)r[r rrRrSrTrUrs r$r.zQuaternion.normms[ :: Aa!##q&1336!9ACCF!BCD Dzzr1c2|}|d|jz zS)z.Returns the normalized form of the quaternion.rbrrs r$ normalizezQuaternion.normalizews AaffhJr1c|}|js tdt|d|jdzz zS)z&Returns the inverse of the quaternion.z6Cannot compute inverse for a quaternion with zero normrbr&)r.r*rrs r$inversezQuaternion.inverse|s9 vvxUV V|q1}--r1c |t|}}|dkr|j| }}|dk(r|St dddd}|dkDr|dzr||z}||z}|dz}|dkDr|S#t$r tcYSwxYw)aFinds 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*NotImplementedrrG)r\rrress r$rzQuaternion.pows2 "qA q599;qA 6HAq!$!e1uq FA !GA !e  ! "! ! "s AA/.A/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)aReturns 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.exps, 1336ACCF?QSS!V34 Hs;' ' Hs;' '!## - ; Hs;' '!## - ; Hs;' '!## - ;!Q1%%r1c|}t|jdz|jdzz|jdzz}|j }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\rrq_normrRrSrTrUs r$r zQuaternion.logs 1336ACCF?QSS!V34  vJ CC$qssV|$ ${ 2 CC$qssV|$ ${ 2 CC$qssV|$ ${ 2!Q1%%r1c|jDcgc]}|j|}}|j}||j|}t||t |d|iScc}w)Nr.)rZsubsr[r0rG)r\rZr#r-r.s r$ _eval_subszQuaternion._eval_subssa+/995aFAFFDM55zz  499d#DHd#8/$// 6sAct|}t|jDcgc]}|j|c}Scc}w)a Returns the floating point approximations (decimal numbers) of the quaternion. Returns ======= Quaternion Floating point approximations of quaternion(self) Examples ======== >>> from sympy import Quaternion >>> from sympy import sqrt >>> q = Quaternion(1/sqrt(1), 1/sqrt(2), 1/sqrt(3), 1/sqrt(4)) >>> q.evalf() 1.00000000000000 + 0.707106781186547*i + 0.577350269189626*j + 0.500000000000000*k )rx)rrGrZevalf)r\precnprecargs r$ _eval_evalfzQuaternion._eval_evalfs6,D!$))D3CIII.DEEDs<c|}|j\}}tj|||z}||j|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_anglerGrvr.)r\rrvrrs r$ pow_cos_sinzQuaternion.pow_cos_sin sD< __& E  ' '1u9 5QVVXq[!!r1c tt|jg|t|jg|t|jg|t|j g|S)aComputes 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 )rGrrRrSrTrUrs r$rzQuaternion.integrate-sT:)DFF2T2Idff4Lt4L#DFF2T2Idff4Lt4LN Nr1ct|trtj|d|d}n|j }|td|d|d|dzt |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&) rrrGrvrrrSrTrU)pinrrpouts r$ rotate_pointzQuaternion.rotate_pointMsyH a **1Q416A A:aQQQ889Q<G''r1c|}|jjr|dz}|j}tdt |jz}t d|j|jzz }t|j |z }t|j|z }t|j|z }|||f}||f}|S)aReturns 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 rr&rb) rR is_negativerrr r rSrTrU) r\rrrrrrrts r$rzQuaternion.to_axis_anglezs*  33??BA KKMT!##Y' QSSW  QSS1W  QSS1W  QSS1W  1I Jr1c ^|}|jdz}|r||jdz|jdzz|jdzz |jdzz z}||jdz|jdzz |jdzz|jdzz z}||jdz|jdzz |jdzz |jdzzz}nxdd|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| | |ggS|\}}}|||zz ||zz || zz }||| zz ||zz || zz }||| zz || zz ||zz }dx}x}}d}t ||| |g| || |g| | ||g||||ggS)aReturns 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 homogeneousrrm00m11m22m01m02m10m12m20m21rrrm03m13m23m30m31m32m33s r$to_rotation_matrixzQuaternion.to_rotation_matrixs$N  FFHbL QSS!Vacc1f_qssAv-Q67CQSS!Vacc1f_qssAv-Q67CQSS!Vacc1f_qssAv-Q67Cac1336ACCF?++Cac1336ACCF?++Cac1336ACCF?++Cc133qss7QSSW$%c133qss7QSSW$%c133qss7QSSW$%c133qss7QSSW$%c133qss7QSSW$%c133qss7QSSW$%Cc?S#sOc3_MN NIQ1ae)ae#ae+Cae)ae#ae+Cae)ae#ae+C C #CCc3/#sC1ES#.c30DFG Gr1c|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_parts $vv r1cZtd|j|j|jS)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!.!TVVTVVTVV44r1c|jj}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)r rrGrSrTrU)r\axiss r$r zQuaternion.axiss82!++-!TVVTVVTVV44r1c.|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 )rRis_zeror_s r$is_purezQuaternion.is_pure8s2vv~~r1c6|jjS)a Returns true if the quaternion is a zero quaternion or false if it is not a zero quaternion and None if the value is unknown. Explanation =========== A zero quaternion is a quaternion with both scalar part and vector part equal to 0. Examples ======== >>> from sympy.algebras.quaternion import Quaternion >>> q = Quaternion(1, 0, 0, 0) >>> q.is_zero_quaternion() False >>> q = Quaternion(0, 0, 0, 0) >>> q.is_zero_quaternion() True See Also ======== scalar_part vector_part )r.r r_s r$rzQuaternion.is_zero_quaternionSs<yy{"""r1ctdt|jj|jzS)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&)rr r.rr_s r$rzQuaternion.angless1.5))+002D4D4D4FGGGr1c&|js|jr tdt|j|jz j|j|jzjgS)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)rr*rr rs r$ arc_coplanarzQuaternion.arc_coplanarspT  # # %5+C+C+EHI I$))+ 4HHJTYY[[`[e[e[gMgL{L{L}~r1ct|js2t|jst|jr tdt|j|j |j g|j|j |j g|j|j |j ggj}|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*rirSrTrUrr )rQrrq3rs r$vector_coplanarzQuaternion.vector_coplanarsl RZZ\ "i &=2::>> 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 purerrr*rrs r$parallelzQuaternion.parallelsHJ T\\^ $ %--/(BDE EU U4Z';;==r1ct|jst|jr td||z||zzjS)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 rrrs r$ orthogonalzQuaternion.orthogonal"sHJ T\\^ $ %--/(BAB BU U4Z';;==r1cD|j|jzS)a Returns the index vector of the quaternion. Explanation =========== The index vector is given by $\mathbf{T}(q)$, the norm (or magnitude) of the quaternion $q$, multiplied by $\mathbf{Ax}(q)$, the axis of $q$. Returns ======= Quaternion: representing index vector of the provided quaternion. Examples ======== >>> from sympy.algebras.quaternion import Quaternion >>> q = Quaternion(2, 4, 2, 4) >>> q.index_vector() 0 + 4*sqrt(10)/3*i + 2*sqrt(10)/3*j + 4*sqrt(10)/3*k See Also ======== axis norm )r.r r_s r$ index_vectorzQuaternion.index_vectorLs>yy{TYY[((r1c4t|jS)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 )rr.r_s r$mensorzQuaternion.mensorms*$))+r1)rrrrTN)F)TF)NT)A__name__ __module__ __qualname____doc__ _op_priorityrJrNrPpropertyrRrSrTrUrVrjrlro classmethodrsrrrvrrrrrrrrrrrrrr staticmethodrrr.rrrr r rrrrrrrrr r rrrrrrrrr __classcell__)rXs@r$rGrG:s/`LN"H  /4/4b4444l/%b()()T=*=*~L!\((T)&)&V"88>))%L4"l'8RI%I%V?  .+Z&>&40F2!"FN@*(*(X&PJGX(525:6#@H4-@^99v(>T(>T)Br1rGN)-sympy.core.numbersrsympy.core.singletonrsympy.core.relationalr$sympy.functions.elementary.complexesrrrr &sympy.functions.elementary.exponentialr r r(sympy.functions.elementary.miscellaneousr (sympy.functions.elementary.trigonometricr rrrrsympy.simplify.trigsimprsympy.integrals.integralsrsympy.matrices.denserrisympy.core.sympifyrrsympy.core.exprrsympy.core.logicrrsympy.utilities.miscrmpmath.libmp.libmpfrr0rErGr(r1r$r8sS'"'JJC9HH?,/=0 0'+=6HHr1