
    3j]                         S SK Jr  S SKJrJrJrJr  S SKrS SKJr  S SK	J
r
  S SKJrJrJrJrJrJrJr  S SKJr   " S S	\R*                  5      rSS
S	S\\R.                     SS	4S jjrg)    )pi)AnyOptionalTupleUnionN)nn)KORNIA_CHECK_TYPE)axis_angle_to_quaternioneuler_from_quaternionnormalize_quaternionquaternion_from_eulerquaternion_to_axis_anglequaternion_to_rotation_matrixrotation_matrix_to_quaternion)batched_dot_productc                   T  ^  \ rS rSr% Sr\\R                  \R                  4   \
S'   S\\R                  \R                  4   SS4U 4S jjrS\S	\SS 4S
 jrS\\R                  \4   SS 4S jrS\4S jrS\\\4   SS 4S jrSJS jrS\S \R                  \4   SS 4S jrS\S \R                  \4   SS 4S jrS\S \R                  \4   SS 4S jrS\\R                  \4   SS 4S jrS\\R                  S \4   SS 4S jrS\\R                  S \4   SS 4S jrS\\R                  \4   SS 4S jrS\\R                  \4   SS 4S jrS\\R                  \4   SS 4S jrS\\R                  \4   SS 4S jrS\SS 4S jr \!S\R                  4S j5       r"\!S\#\R                  \R                  \R                  \R                  4   4S  j5       r$\!S\R                  4S! j5       r%\!S\R                  4S" j5       r&\!S\R                  4S# j5       r'\!S\R                  4S$ j5       r(\!S\R                  4S% j5       r)\!S\R                  4S& j5       r*\!S\R                  4S' j5       r+\!S\R                  4S( j5       r,\!S\#\S)4   4S* j5       r-\!S\R                  4S+ j5       r.S\R                  4S, jr/\0S-\R                  SS 4S. j5       r1\0S/\R                  S0\R                  S1\R                  SS 4S2 j5       r2S\#\R                  \R                  \R                  4   4S3 jr3\0S4\R                  SS 4S5 j5       r4S\R                  4S6 jr5\0   SKS7\6\   S8\S\\Rn                  4   S9\\Rp                  S4   SS 4S: jj5       r9\0S;\S<\S=\S>\SS 4
S? j5       r:\0   SKS7\6\   S8\S\\Rn                  4   S9\\Rp                  S4   SS 4S@ jj5       r;SAS S\SS 4SB jr<SLSC\=S\R                  4SD jjr>SJSE jr?SJSF jr@SJSG jrAS\R                  4SH jrBSIrCU =rD$ )M
Quaternion)   ag  Base class to represent a Quaternion.

A quaternion is a four dimensional vector representation of a rotation transformation in 3d.
See more: https://en.wikipedia.org/wiki/Quaternion

The general definition of a quaternion is given by:

.. math::

    Q = a + b \cdot \mathbf{i} + c \cdot \mathbf{j} + d \cdot \mathbf{k}

Thus, we represent a rotation quaternion as a contiguous torch.Tensor structure to
perform rigid bodies transformations:

.. math::

    Q = \begin{bmatrix} q_w & q_x & q_y & q_z \end{bmatrix}

Example:
    >>> q = Quaternion.identity(batch_size=4)
    >>> q.data
    tensor([[1., 0., 0., 0.],
            [1., 0., 0., 0.],
            [1., 0., 0., 0.],
            [1., 0., 0., 0.]])
    >>> q.real
    tensor([1., 1., 1., 1.])
    >>> q.vec
    tensor([[0., 0., 0.],
            [0., 0., 0.],
            [0., 0., 0.],
            [0., 0., 0.]])

_datadatareturnNc                    > [         TU ]  5         [        U[        R                  [
        R                  45      (       d  [        S[        U5       35      eXl	        g)a  Construct a quaternion from torch.Tensor or parameter data.

Args:
    data: torch.Tensor or parameter containing the quaternion data with the shape of :math:`(B, 4)`.

Example:
    >>> # Create with torch.tensor(no gradients tracked by default)
    >>> data = torch.tensor([1., 0., 0., 0.])
    >>> q1 = Quaternion(data)
    >>> # Create with parameter (gradients tracked)
    >>> param_data = torch.nn.Parameter(torch.tensor([1., 0., 0., 0.]))
    >>> q2 = Quaternion(param_data)

z+Expected torch.Tensor or nn.Parameter, got N)
super__init__
isinstancetorchTensorr   	Parameter	TypeErrortyper   )selfr   	__class__s     T/home/wildlama/miniconda3/lib/python3.13/site-packages/kornia/geometry/quaternion.pyr   Quaternion.__init__O   sF     	$r|| <==I$t*VWW
    argskwargsc                 L    [        U R                  R                  " U0 UD65      $ )zMove and/or cast the quaternion data.

Args:
    *args: Arguments to pass to torch.Tensor.to()
    **kwargs: Keyword arguments to pass to torch.Tensor.to()

Returns:
    A new Quaternion with converted data.
)r   r   to)r!   r&   r'   s      r#   r)   Quaternion.tod   s!     $**--8899r%   valuec                    [        U[        [        45      (       a>  [        R                  " XR
                  R                  U R
                  R                  S9nOW[        U[        R                  5      (       a8  UR                  U R
                  R                  U R
                  R                  S9n [        R                  " U R                  R                  UR                  5      nU R                  R                  U5      UR                  U5      -   nUR!                  5       S:X  a  UR#                  U5      nO [        R$                  " XR                  5      n[        R&                  " U5      R)                  S5      R                  " / UR                  QSP76 n[        R*                  " UR)                  S5      U/SS9n[-        U5      $ ! [         a5  n[        SU R                  R                   SUR                   35      UeSnAff = f)	a)  Convert a scalar, torch.Tensor, or numeric value to a scalar quaternion.

A scalar quaternion has the form [real, 0, 0, 0] where real is the input value.

Args:
    value: The scalar, torch.Tensor, or numeric value to convert.

Returns:
    A Quaternion object representing the scalar quaternion.
devicedtypezCannot broadcast shapes z and Nr      dim)r   intfloatr   tensorr   r.   r/   r   r)   broadcast_shapesrealshapeRuntimeError
ValueErrorexpandr3   	expand_asbroadcast_to
zeros_like	unsqueezecatr   )r!   r+   target_shapeebroadcastedexpanded_valuezerosscalar_quat_datas           r#   _to_scalar_quaternion Quaternion._to_scalar_quaternionp   s    ec5\**LLyy/?/?tyyWEu||,,HHDII$4$4DIIOOHLE	d 11$))//5;;OL ii&&|4u||L7QQ 99;!"__[9N #//7H7HIN   0::2>EE_~G[G[_]^_ !99n&>&>r&BE%JPRS*++'  	d7		7Hekk][\bcc	ds   25G 
H0HHc                     U R                    $ Nr   r!   s    r#   __repr__Quaternion.__repr__   s    ))r%   idxc                 2    [        U R                  U   5      $ rK   r   r   )r!   rP   s     r#   __getitem__Quaternion.__getitem__   s    $))C.))r%   c                 .    [        U R                  * 5      $ )zInverts the sign of the quaternion data.

Example:
    >>> q = Quaternion.identity()
    >>> -q.data
    tensor([-1., -0., -0., -0.])

rR   rM   s    r#   __neg__Quaternion.__neg__   s     499*%%r%   rightc                     [        U[        5      (       a"  [        U R                  UR                  -   5      $ U R                  U5      n[        U R                  UR                  -   5      $ )a  Add a given quaternion, scalar, or torch.Tensor.

Args:
    right: the quaternion, scalar, or torch.Tensor to add.

Example:
    >>> q1 = Quaternion.identity()
    >>> q2 = Quaternion(torch.tensor([2., 0., 1., 1.]))
    >>> q3 = q1 + q2
    >>> q3.data
    tensor([3., 0., 1., 1.])

)r   r   r   rH   )r!   rX   
right_quats      r#   __add__Quaternion.__add__   sQ     eZ((dii%**45533E:Jdii*//9::r%   c                 0   [        U[        5      (       a"  [        U R                  UR                  -
  5      $ U R                  U5      nU R                  UR                  -
  n[        U[        R
                  5      (       a  UR                  n[        U5      $ )a%  Subtract a given quaternion, scalar, or torch.Tensor.

Args:
    right: the quaternion, scalar, or torch.Tensor to subtract.

Example:
    >>> q1 = Quaternion(torch.tensor([2., 0., 1., 1.]))
    >>> q2 = Quaternion.identity()
    >>> q3 = q1 - q2
    >>> q3.data
    tensor([1., 0., 1., 1.])

)r   r   r   rH   r   r   )r!   rX   rZ   result_datas       r#   __sub__Quaternion.__sub__   sr     eZ((dii%**45533E:J))joo5K+r||44)..k**r%   c                 ~   [        U[        5      (       a  U R                  UR                  -  [        U R                  UR                  5      -
  nU R                  S   UR                  -  UR                  S   U R                  -  -   [
        R                  R                  U R                  UR                  SS9-   n[        [
        R                  " US   U4S5      5      $ U R                  U5      nU R                  UR                  -  [        U R                  UR                  5      -
  nU R                  S   UR                  -  UR                  S   U R                  -  -   [
        R                  R                  U R                  UR                  SS9-   n[        [
        R                  " US   U4S5      5      $ )N.Nr0   r2   )
r   r   r8   r   vecr   linalgcrossrA   rH   )r!   rX   new_realnew_vecrZ   s        r#   __mul__Quaternion.__mul__   sl   eZ((yy5::-0CDHHeii0XXH		)$uyy0**Y'$((23,,$$TXXuyyb$AB 
 eii))<g(FKLL 33E:Jyy:??25HS]SaSa5bbH		)$z~~5//),txx78,,$$TXXz~~2$FG 
 eii))<g(FKLLr%   leftc                    U R                  U5      nUR                  U R                  -  [        UR                  U R                  5      -
  nUR                  S   U R                  -  U R                  S   UR                  -  -   [        R
                  R                  UR                  U R                  SS9-   n[        [        R                  " US   U4S5      5      $ )zJRight multiplication (left * self) where left is a scalar or torch.Tensor.rb   r0   r2   )	rH   r8   r   rc   r   rd   re   r   rA   )r!   rj   	left_quatrf   rg   s        r#   __rmul__Quaternion.__rmul__   s    ..t4	>>DII-0CIMMSWS[S[0\\NN9%0ii	"Y]]23ll  b AB 	
 %))Xi%8'$BBGHHr%   c                    [        U[        5      (       a  XR                  5       -  $ [        U[        [        45      (       a>  [
        R                  " XR                  R                  U R                  R                  S9nO8UR                  U R                  R                  U R                  R                  S9nUR                  5       S:X  aG  UR                  U R                  S   5      R                  S5      R                  U R                  5      nO*UR                  S5      R                  U R                  5      nU R                  U-  n[        U[        R                  5      (       a  UR                  n[        U5      $ )Nr-   r   .r   r0   )r   r   invr4   r5   r   r6   r   r.   r/   r)   r3   r=   r@   r   r   )r!   rX   right_tensordivisorr^   s        r#   __div__Quaternion.__div__   s   eZ(())+%% %#u..$||E)):J:JRVR[R[RaRab$xxtyy/?/?tyyxW !Q&&0061BCMMbQ[[\`\e\ef '004>>tyyI ))g-K+r||44)..k**r%   c                 $    U R                  U5      $ rK   )rt   )r!   rX   s     r#   __truediv__Quaternion.__truediv__  s    ||E""r%   c                 ,    U R                  U5      nX -   $ )zDRight addition (left + self) where left is a scalar or torch.Tensor.rH   r!   rj   rl   s      r#   __radd__Quaternion.__radd__      ..t4	r%   c                 ,    U R                  U5      nX -
  $ )zGRight subtraction (left - self) where left is a scalar or torch.Tensor.rz   r{   s      r#   __rsub__Quaternion.__rsub__  r~   r%   c                 ,    U R                  U5      nX -  $ zDRight division (left / self) where left is a scalar or torch.Tensor.rz   r{   s      r#   __rtruediv__Quaternion.__rtruediv__  r~   r%   c                 $    U R                  U5      $ r   )r   )r!   rj   s     r#   __rdiv__Quaternion.__rdiv__  s      &&r%   tc                 N   U R                   S   nU R                  R                  SSS9n[        R                  " US:g  U R                  U-  U R                  S-  5      nX-  R                  5       nX-  R                  5       U-  n[        [        R                  " XV4S5      5      $ )zReturn the power of a quaternion raised to exponent t.

Args:
    t: raised exponent.

Example:
    >>> q = Quaternion(torch.tensor([1., .5, 0., 0.]))
    >>> q_pow = q**2

rb   r0   T)r3   keepdimr   )	polar_anglerc   normr   wherecossinr   rA   )r!   r   thetavec_normnwxyzs          r#   __pow__Quaternion.__pow__#  s       +88==R=6KKAtxx(':DHHqLIYOOyoo!#%))QHb122r%   c                     U R                   $ )z5Return the underlying data with shape :math:`(B, 4)`.r   rM   s    r#   r   Quaternion.data5  s     zzr%   c                 ^    U R                   U R                  U R                  U R                  4$ )z>Return a tuple with the underlying coefficients in WXYZ order.)r   xyzrM   s    r#   coeffsQuaternion.coeffs:  s#     vvtvvtvvtvv--r%   c                     U R                   $ )zkReturn the real part with shape :math:`(B,)`.

Alias for
:func: `~kornia.geometry.quaternion.Quaternion.w`
)r   rM   s    r#   r8   Quaternion.real?  s     vvr%   c                 (    U R                   SSS24   $ )zDReturn the vector with the imaginary part with shape :math:`(B, 3)`..   NrL   rM   s    r#   rc   Quaternion.vecH  s     yyab!!r%   c                     U R                   $ )zuReturn the underlying data with shape :math:`(B, 4)`.

Alias for :func:`~kornia.geometry.quaternion.Quaternion.data`
rL   rM   s    r#   qQuaternion.qM  s     yyr%   c                     U R                   $ )ztReturn a scalar with the real with shape :math:`(B,)`.

Alias for
:func: `~kornia.geometry.quaternion.Quaternion.w`
)r8   rM   s    r#   scalarQuaternion.scalarU  s     yyr%   c                      U R                   S   $ )z/Return the :math:`q_w` with shape :math:`(B,)`.rp   rL   rM   s    r#   r   Quaternion.w^       yy  r%   c                      U R                   S   $ )z/Return the :math:`q_x` with shape :math:`(B,)`.).r   rL   rM   s    r#   r   Quaternion.xc  r   r%   c                      U R                   S   $ )z/Return the :math:`q_y` with shape :math:`(B,)`.).   rL   rM   s    r#   r   Quaternion.yh  r   r%   c                      U R                   S   $ )z/Return the :math:`q_z` with shape :math:`(B,)`.).r1   rL   rM   s    r#   r   Quaternion.zm  r   r%   .c                 @    [        U R                  R                  5      $ )zBReturn the shape of the underlying data with shape :math:`(B, 4)`.)tupler   r9   rM   s    r#   r9   Quaternion.shaper  s     TYY__%%r%   c                 X    U R                   U R                  5       -  R                  5       $ )zReturn the polar angle with shape :math:`(B,1)`.

Example:
    >>> q = Quaternion.identity()
    >>> q.polar_angle
    tensor(0.)

)r   r   acosrM   s    r#   r   Quaternion.polar_anglew  s"     diik)//11r%   c                 ,    [        U R                  5      $ )zConvert the quaternion to a rotation matrix of shape :math:`(B, 3, 3)`.

Example:
    >>> q = Quaternion.identity()
    >>> m = q.matrix()
    >>> m
    tensor([[1., 0., 0.],
            [0., 1., 0.],
            [0., 0., 1.]])

)r   r   rM   s    r#   matrixQuaternion.matrix  s     -TYY77r%   r   c                 $    U " [        U5      5      $ )zCreate a quaternion from a rotation matrix.

Args:
    matrix: the rotation matrix to convert of shape :math:`(B, 3, 3)`.

Example:
    >>> m = torch.eye(3)[None]
    >>> q = Quaternion.from_matrix(m)
    >>> q.data
    tensor([[1., 0., 0., 0.]])

)r   )clsr   s     r#   from_matrixQuaternion.from_matrix  s     0899r%   rollpitchyawc                 ^    [        XUS9u  pEpg[        R                  " XEXg4S5      nU " U5      $ )aV  Create a quaternion from Euler angles.

Args:
    roll: the roll euler angle.
    pitch: the pitch euler angle.
    yaw: the yaw euler angle.

Example:
    >>> roll, pitch, yaw = torch.tensor(0), torch.tensor(1), torch.tensor(0)
    >>> q = Quaternion.from_euler(roll, pitch, yaw)
    >>> q.data
    tensor([0.8776, 0.0000, 0.4794, 0.0000])

)r   r   r   r0   )r   r   stack)	r   r   r   r   r   r   r   r   r   s	            r#   
from_eulerQuaternion.from_euler  s1      +sK
aKKqb)1vr%   c                 n    [        U R                  U R                  U R                  U R                  5      $ )a  Convert the quaternion to a triple of Euler angles (roll, pitch, yaw).

Example:
    >>> q = Quaternion(torch.tensor([2., 0., 1., 1.]))
    >>> roll, pitch, yaw = q.to_euler()
    >>> roll
    tensor(2.0344)
    >>> pitch
    tensor(1.5708)
    >>> yaw
    tensor(2.2143)

)r   r   r   r   r   rM   s    r#   to_eulerQuaternion.to_euler  s%     %TVVTVVTVVTVVDDr%   
axis_anglec                 $    U " [        U5      5      $ )a"  Create a quaternion from axis-angle representation.

Args:
    axis_angle: rotation vector of shape :math:`(B, 3)`.

Example:
    >>> axis_angle = torch.tensor([[1., 0., 0.]])
    >>> q = Quaternion.from_axis_angle(axis_angle)
    >>> q.data
    tensor([[0.8776, 0.4794, 0.0000, 0.0000]])

)r
   )r   r   s     r#   from_axis_angleQuaternion.from_axis_angle  s     +J788r%   c                 ,    [        U R                  5      $ )zConvert the quaternion to an axis-angle representation.

Example:
    >>> q = Quaternion.identity()
    >>> axis_angle = q.to_axis_angle()
    >>> axis_angle
    tensor([0., 0., 0.])

)r   r   rM   s    r#   to_axis_angleQuaternion.to_axis_angle  s     (		22r%   
batch_sizer.   r/   c                 j    [         R                  " / SQX#S9nUb  UR                  US5      nU " U5      $ )a  Create a quaternion representing an identity rotation.

Args:
    batch_size: the batch size of the underlying data.
    device: device to place the result on.
    dtype: dtype of the result.

Example:
    >>> q = Quaternion.identity()
    >>> q.data
    tensor([1., 0., 0., 0.])

)      ?        r   r   r-   r   )r   r6   repeat)r   r   r.   r/   r   s        r#   identityQuaternion.identity  s5    ( ||0M!;;z1-D4yr%   r   r   r   r   c                 >    U " [         R                  " XX4/5      5      $ )a}  Create a quaternion from the data coefficients.

Args:
    w: a float representing the :math:`q_w` component.
    x: a float representing the :math:`q_x` component.
    y: a float representing the :math:`q_y` component.
    z: a float representing the :math:`q_z` component.

Example:
    >>> q = Quaternion.from_coeffs(1., 0., 0., 0.)
    >>> q.data
    tensor([1., 0., 0., 0.])

)r   r6   )r   r   r   r   r   s        r#   from_coeffsQuaternion.from_coeffs  s      5<<q-..r%   c                    Ub  U4OSn[         R                  " S/UQ7X#S9u  pVnSU-
  R                  5       S[        -  U-  R	                  5       -  nSU-
  R                  5       S[        -  U-  R                  5       -  n	UR                  5       S[        -  U-  R	                  5       -  n
UR                  5       S[        -  U-  R                  5       -  nU " [         R                  " XX4S5      5      $ )a{  Create a random unit quaternion of shape :math:`(B, 4)`.

Uniformly distributed across the rotation space as per: http://planning.cs.uiuc.edu/node198.html

Args:
    batch_size: the batch size of the underlying data.
    device: device to place the result on.
    dtype: dtype of the result.

Example:
    >>> q = Quaternion.random()
    >>> q = Quaternion.random(batch_size=2)

 r1   r-   r   r   r0   )r   randsqrtr   r   r   r   )r   r   r.   r/   
rand_shaper1r2r3q1q2q3q4s               r#   randomQuaternion.random  s    * '1&<j]"
ZZ 0Z 0M
Bh__1r6B;"3"3"56Bh__1r6B;"3"3"56WWY!b&2+**,,WWY!b&2+**,,5;;/455r%   r   c                     [        U[        5        U R                  5       nUR                  5       nX3R                  5       U-  U-  -  $ )am  Return a unit quaternion spherically interpolated between quaternions self.q and q1.

See more: https://en.wikipedia.org/wiki/Slerp

Args:
    q1: second quaternion to be interpolated between.
    t: interpolation ratio, range [0-1]

Example:
    >>> q0 = Quaternion.identity()
    >>> q1 = Quaternion(torch.tensor([1., .5, 0., 0.]))
    >>> q2 = q0.slerp(q1, .3)

)r	   r   	normalizerq   )r!   r   r   q0s       r#   slerpQuaternion.slerp,  s=     	"j)^^\\^VVX]q(((r%   r   c                 <    U R                   R                  SSU5      $ )zCompute the norm (magnitude) of the quaternion.

Args:
    keepdim: whether to retain the last dimension.

Returns:
    The norm of the quaternion(s) as a torch.Tensor.

Example:
    >>> q = Quaternion.identity()
    >>> q.norm()
    tensor(1.)

r   r0   )r   r   )r!   r   s     r#   r   Quaternion.norm@  s      yy~~aW--r%   c                 >    [        [        U R                  5      5      $ )zReturn a normalized (unit) quaternion.

Returns:
    The normalized quaternion.

Example:
    >>> q = Quaternion(torch.tensor([2., 1., 0., 0.]))
    >>> q_norm = q.normalize()

)r   r   r   rM   s    r#   r   Quaternion.normalizeR  s     .tyy9::r%   c                 v    [        [        R                  " U R                  S   U R                  * 4S5      5      $ )zCompute the conjugate of the quaternion.

Returns:
    The conjugate quaternion, with the vector part negated.

Example:
    >>> q = Quaternion(torch.tensor([1., 2., 3., 4.]))
    >>> q_conj = q.conj()

rb   r0   )r   r   rA   r8   rc   rM   s    r#   conjQuaternion.conj_  s.     %))TYYy%9DHH9$ErJKKr%   c                 D    U R                  5       U R                  5       -  $ )zCompute the inverse of the quaternion.

Returns:
    The inverse quaternion.

Example:
    >>> q = Quaternion.identity()
    >>> q_inv = q.inv()

)r   squared_normrM   s    r#   rq   Quaternion.invl  s     yy{T..000r%   c                 b    [        U R                  U R                  5      U R                  S-  -   $ )zCompute the squared norm (magnitude) of the quaternion.

Returns:
    The squared norm of the quaternion(s) as a torch.Tensor.

Example:
    >>> q = Quaternion.identity()
    >>> q.squared_norm()
    tensor(1.)

r   )r   rc   r8   rM   s    r#   r   Quaternion.squared_normy  s&     #488TXX6AEEr%   r   )r   r   )NNN)F)E__name__
__module____qualname____firstlineno____doc__r   r   r   r   r   __annotations__r   r   r)   r5   rH   strrN   r4   slicerS   rV   r[   r_   rh   rm   rt   rw   r|   r   r   r   r   propertyr   r   r   r8   rc   r   r   r   r   r   r   r9   r   r   classmethodr   r   r   r   r   r   r.   r/   r   r   r   r   boolr   r   r   rq   r   __static_attributes____classcell__)r"   s   @r#   r   r   )   s   !F r||+,,U5<<#=> 4 *
: 
:s 
:| 
:&,5u1D+E &,, &,P# *uS%Z0 *\ *	&;U<u#DE ;, ;(+U<u#DE +, +0MU<u#DE M, M,	IU5<<#67 	IL 	I+U5<<u#DE +, +.#u||\5'H!I #l # U5<<#67  L  
 U5<<#67  L  
 u||U':!;    
'U5<<#67 'L '3 3< 3$ ell   .ellELL%,,TU . . ell   "U\\ " " 5<<      !5<< ! ! !5<< ! ! !5<< ! ! !5<< ! ! &uS#X & & 	2U\\ 	2 	28 8 : :, : : ell 5<< ell Wc  &E%ellELL HI E  9 9, 9 9
3u|| 
3  %)15*.	SM dC-. U[[$&'	
 
 0 /E /e / /% /L / /&  %)15*.	6SM6 dC-.6 U[[$&'	6
 
6 6:) ) )< )(.D .U\\ .$;L1Fell F Fr%   r   Qr   r   c                 0   U R                   n[        U [        5        UR                  S   nUc  UR                  U-  U-  nOUR                  UR                  UR                  S9nUR                  5       U:w  a  [        SUR                  5        SU 35      eXR                  5       -  nUR                  [        R                  " U5      -  U-  nUR                  nUR                  [        R                  [        R                  4;   a  UR                  5       n[        R                   R#                  U5      u  pg[        R$                  " U5      nUR                  U5      nUSS2U4   n	XR'                  5       -  n	[        U	R)                  S5      5      $ )a?  Compute (weighted) average of multiple quaternions.

Args:
    Q (Quaternion): quaternion object containing data of shape (M, 4).
    w (torch.Tensor, optional): Weights of shape (M,). If None, uniform weights are used.


Returns:
    Quaternion: averaged quaternion (shape (4,)), wrapped back in the Quaternion class.
r   N)r/   zweights length z" must match number of quaternions )r   r	   r   r9   Tr)   r.   r/   numelr;   sumr   diagfloat16bfloat16r5   rd   eighargmaxr   r@   )
r
  r   r   MA
orig_dtypeeigenvalueseigenvectorsmax_idxq_avgs
             r#   average_quaternionsr    s=    66Da$

1AyVVd]aDDDJJD/779>qwwyk9[\][^_``KFFUZZ]"T)Jww5==%..11GGI % 1 1! 4K ll;'G??:.LG$EJJL Eeooa())r%   rK   )mathr   typingr   r   r   r   r   r   kornia.core.checkr	   kornia.geometry.conversionsr
   r   r   r   r   r   r   kornia.geometry.linalgr   Moduler   r   r  r   r%   r#   <module>r"     se   ,  . .   /   7\	F \	F~#*< #*HU\\,B #*l #*r%   