o
    oi`&                     @  s   d dl mZ d dlmZmZ d dlmZmZmZm	Z	m
Z
mZmZmZmZmZ d dlmZmZ d dlmZmZmZmZmZ d dlmZ G dd deZd	S )
    )annotations)Optionaloverload)
DeviceDtypeModule	ParameterTensorcomplexrandstacktensor
zeros_like)KORNIA_CHECKKORNIA_CHECK_IS_TENSOR)check_so2_matrixcheck_so2_matrix_shapecheck_so2_t_shapecheck_so2_theta_shapecheck_so2_z_shape)Vector2c                      s   e Zd ZdZd5 fddZd6d	d
Zd7ddZed8ddZed9ddZd:ddZe	d;ddZ
ed<ddZd;ddZed=ddZed>dd Zd;d!d"Zed?d$d%Ze	&d@dAd-d.ZdBd/d0Ze	&d@dAd1d2Zd;d3d4Z  ZS )CSo2a(  Base class to represent the So2 group.

    The SO(2) is the group of all rotations about the origin of two-dimensional Euclidean space
    :math:`R^2` under the operation of composition.
    See more: https://en.wikipedia.org/wiki/Orthogonal_group#Special_orthogonal_group

    We internally represent the rotation by a complex number.

    Example:
        >>> real = torch.tensor([1.0])
        >>> imag = torch.tensor([2.0])
        >>> So2(torch.complex(real, imag))
        Parameter containing:
        tensor([1.+2.j], requires_grad=True)

    zr	   returnNonec                   s(   t    t| t| t|| _dS )a  Construct the base class.

        Internally represented by complex number `z`.

        Args:
            z: Complex number with the shape of :math:`(B, 1)` or :math:`(B)`.

        Example:
            >>> real = torch.tensor(1.0)
            >>> imag = torch.tensor(2.0)
            >>> So2(torch.complex(real, imag)).z
            Parameter containing:
            tensor(1.+2.j, requires_grad=True)

        N)super__init__r   r   r   _z)selfr   	__class__ P/home/ubuntu/.local/lib/python3.10/site-packages/kornia/geometry/liegroup/so2.pyr   6   s   
zSo2.__init__strc                 C  s   | j  S N)r   r   r!   r!   r"   __repr__L   s   zSo2.__repr__idxint | slicec                 C  s   t | j| S r$   )r   r   )r   r'   r!   r!   r"   __getitem__O   s   zSo2.__getitem__rightc                 C     d S r$   r!   r   r*   r!   r!   r"   __mul__R      zSo2.__mul__c                 C  r+   r$   r!   r,   r!   r!   r"   r-   U   r.   So2 | Tensorc                 C  s   | j }t|trt||j  S t|ttfrMt|trt| |jd }|jd }|j}|j}t	|| ||  || ||  fd}t|trI|S t|S t
dt| )zPerform a left-multiplication either rotation concatenation or point-transform.

        Args:
            right: the other So2 transformation.

        Return:
            The resulting So2 transformation.

        ).r   ).   zNot So2 or Tensor type. Got: )r   
isinstancer   r   r	   r   datarealimagr   	TypeErrortype)r   r*   r   xyr4   r5   outr!   r!   r"   r-   X   s   




&
c                 C  s   | j S )z5Return the underlying data with shape :math:`(B, 1)`.)r   r%   r!   r!   r"   r   u   s   zSo2.zthetac                 C  s   t |  tt|  |  S )ai  Convert elements of lie algebra to elements of lie group.

        Args:
            theta: angle in radians of shape :math:`(B, 1)` or :math:`(B)`.

        Example:
            >>> v = torch.tensor([3.1415/2])
            >>> s = So2.exp(v)
            >>> s
            Parameter containing:
            tensor([4.6329e-05+1.j], requires_grad=True)

        )r   r   r
   cossin)r;   r!   r!   r"   expz   s   zSo2.expc                 C  s   | j j| j jS )a  Convert elements of lie group to elements of lie algebra.

        Example:
            >>> real = torch.tensor([1.0])
            >>> imag = torch.tensor([3.0])
            >>> So2(torch.complex(real, imag)).log()
            tensor([1.2490], grad_fn=<Atan2Backward0>)

        )r   r5   atan2r4   r%   r!   r!   r"   log   s   
zSo2.logc                 C  s:   t |  t| }t|| fd}t| |fd}t||fdS )a]  Convert elements from vector space to lie algebra. Returns matrix of shape :math:`(B, 2, 2)`.

        Args:
            theta: angle in radians of shape :math:`(B)`.

        Example:
            >>> theta = torch.tensor(3.1415/2)
            >>> So2.hat(theta)
            tensor([[0.0000, 1.5707],
                    [1.5707, 0.0000]])

        r1   )r   r   r   )r;   r   row0row1r!   r!   r"   hat   s
   zSo2.hatomegac                 C  s   t |  | d S )a@  Convert elements from lie algebra to vector space. Returns vector of shape :math:`(B,)`.

        Args:
            omega: 2x2-matrix representing lie algebra.

        Example:
            >>> v = torch.ones(3)
            >>> omega = So2.hat(v)
            >>> So2.vee(omega)
            tensor([1., 1., 1.])

        ).r   r0   )r   )rD   r!   r!   r"   vee   s   zSo2.veec                 C  s<   t | jj| jj fd}t | jj| jjfd}t ||fdS )a  Convert the complex number to a rotation matrix of shape :math:`(B, 2, 2)`.

        Example:
            >>> s = So2.identity()
            >>> m = s.matrix()
            >>> m
            tensor([[1., -0.],
                    [0., 1.]], grad_fn=<StackBackward0>)

        r1   )r   r   r4   r5   )r   rA   rB   r!   r!   r"   matrix   s   z
So2.matrixrG   c                 C  s*   t | t| t|d |d }| |S )aI  Create So2 from a rotation matrix.

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

        Example:
            >>> m = torch.eye(2)
            >>> s = So2.from_matrix(m)
            >>> s.z
            Parameter containing:
            tensor(1.+0.j, requires_grad=True)

        ).r   r   ).r0   r   )r   r   r
   )clsrG   r   r!   r!   r"   from_matrix   s   zSo2.from_matrixN
batch_sizeOptional[int]deviceOptional[Device]dtypeOptional[Dtype]c                 C  sV   t d||d}t d||d}|dur$t|dkdd ||}||}| t||S )a  Create a So2 group 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:
            >>> s = So2.identity(batch_size=2)
            >>> s
            Parameter containing:
            tensor([1.+0.j, 1.+0.j], requires_grad=True)

        g      ?rL   rN   g        Nr0   batch_size must be positivemsg)r   r   repeatr
   rH   rJ   rL   rN   	real_data	imag_datar!   r!   r"   identity   s   

zSo2.identityc                 C  s   t d| j S )zReturn the inverse transformation.

        Example:
            >>> s = So2.identity()
            >>> s.inverse().z
            Parameter containing:
            tensor(1.+0.j, requires_grad=True)

        r0   )r   r   r%   r!   r!   r"   inverse   s   
zSo2.inversec                 C  sd   |durt |dkdd t|f||d}t|f||d}ntd||d}td||d}| t||S )aE  Create a So2 group representing a random rotation.

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

        Example:
            >>> s = So2.random()
            >>> s = So2.random(batch_size=3)

        Nr0   rQ   rR   rP   r!   )r   r   r
   rU   r!   r!   r"   random
  s   z
So2.randomc                 C  s:   t | jjdkrt | jnd}| || jj| jjj S )zReturn the adjoint matrix of shape :math:`(B, 2, 2)`.

        Example:
            >>> s = So2.identity()
            >>> s.adjoint()
            tensor([[1., -0.],
                    [0., 1.]], grad_fn=<StackBackward0>)

        r   N)lenr   shaperX   rL   r4   rN   rG   )r   rJ   r!   r!   r"   adjoint#  s   
zSo2.adjoint)r   r	   r   r   )r   r#   )r'   r(   r   r   )r*   r   r   r   )r*   r	   r   r	   )r*   r/   r   r/   )r   r	   )r;   r	   r   r   )r;   r	   r   r	   )rD   r	   r   r	   )rG   r	   r   r   )NNN)rJ   rK   rL   rM   rN   rO   r   r   )r   r   )__name__
__module____qualname____doc__r   r&   r)   r   r-   propertyr   staticmethodr>   r@   rC   rE   rG   classmethodrI   rX   rY   rZ   r]   __classcell__r!   r!   r   r"   r   $   s<    





r   N)
__future__r   typingr   r   kornia.corer   r   r   r   r	   r
   r   r   r   r   kornia.core.checkr   r   kornia.geometry.liegroup._utilsr   r   r   r   r   kornia.geometry.vectorr   r   r!   r!   r!   r"   <module>   s   0