def rotation_matrix_to_quaternion(rotation_matrix: torch.Tensor, eps: float=1e-08) -> torch.Tensor:
    'Convert 3x3 rotation matrix to 4d quaternion vector.\n    The quaternion vector has components in (x, y, z, w) format.\n\n    Args:\n        rotation_matrix (torch.Tensor): the rotation matrix to convert.\n        eps (float): small value to avoid zero division. Default: 1e-8.\n\n    Return:\n        torch.Tensor: the rotation in quaternion.\n\n    Shape:\n        - Input: :math:`(*, 3, 3)`\n        - Output: :math:`(*, 4)`\n\n    Example:\n        >>> input = torch.rand(4, 3, 3)  # Nx3x3\n        >>> output = rotation_matrix_to_quaternion(input)  # Nx4\n    '
    if (not isinstance(rotation_matrix, torch.Tensor)):
        raise TypeError('Input type is not a torch.Tensor. Got {}'.format(type(rotation_matrix)))
    if (not (rotation_matrix.shape[(- 2):] == (3, 3))):
        raise ValueError('Input size must be a (*, 3, 3) tensor. Got {}'.format(rotation_matrix.shape))

    def safe_zero_division(numerator: torch.Tensor, denominator: torch.Tensor) -> torch.Tensor:
        eps: float = torch.finfo(numerator.dtype).tiny
        return (numerator / torch.clamp(denominator, min=eps))
    rotation_matrix_vec: torch.Tensor = rotation_matrix.view(*rotation_matrix.shape[:(- 2)], 9)
    (m00, m01, m02, m10, m11, m12, m20, m21, m22) = torch.chunk(rotation_matrix_vec, chunks=9, dim=(- 1))
    trace: torch.Tensor = ((m00 + m11) + m22)

    def trace_positive_cond():
        sq = (torch.sqrt((trace + 1.0)) * 2.0)
        qw = (0.25 * sq)
        qx = safe_zero_division((m21 - m12), sq)
        qy = safe_zero_division((m02 - m20), sq)
        qz = safe_zero_division((m10 - m01), sq)
        return torch.cat([qx, qy, qz, qw], dim=(- 1))

    def cond_1():
        sq = (torch.sqrt(((((1.0 + m00) - m11) - m22) + eps)) * 2.0)
        qw = safe_zero_division((m21 - m12), sq)
        qx = (0.25 * sq)
        qy = safe_zero_division((m01 + m10), sq)
        qz = safe_zero_division((m02 + m20), sq)
        return torch.cat([qx, qy, qz, qw], dim=(- 1))

    def cond_2():
        sq = (torch.sqrt(((((1.0 + m11) - m00) - m22) + eps)) * 2.0)
        qw = safe_zero_division((m02 - m20), sq)
        qx = safe_zero_division((m01 + m10), sq)
        qy = (0.25 * sq)
        qz = safe_zero_division((m12 + m21), sq)
        return torch.cat([qx, qy, qz, qw], dim=(- 1))

    def cond_3():
        sq = (torch.sqrt(((((1.0 + m22) - m00) - m11) + eps)) * 2.0)
        qw = safe_zero_division((m10 - m01), sq)
        qx = safe_zero_division((m02 + m20), sq)
        qy = safe_zero_division((m12 + m21), sq)
        qz = (0.25 * sq)
        return torch.cat([qx, qy, qz, qw], dim=(- 1))
    where_2 = torch.where((m11 > m22), cond_2(), cond_3())
    where_1 = torch.where(((m00 > m11) & (m00 > m22)), cond_1(), where_2)
    quaternion: torch.Tensor = torch.where((trace > 0.0), trace_positive_cond(), where_1)
    return quaternion
Convert 3x3 rotation matrix to 4d quaternion vector.
The quaternion vector has components in (x, y, z, w) format.

Args:
    rotation_matrix (torch.Tensor): the rotation matrix to convert.
    eps (float): small value to avoid zero division. Default: 1e-8.

Return:
    torch.Tensor: the rotation in quaternion.

Shape:
    - Input: :math:`(*, 3, 3)`
    - Output: :math:`(*, 4)`

Example:
    >>> input = torch.rand(4, 3, 3)  # Nx3x3
    >>> output = rotation_matrix_to_quaternion(input)  # Nx4
def rotation_matrix_to_quaternion(rotation_matrix: torch.Tensor, eps: float=1e-08) -> torch.Tensor:
    'Convert 3x3 rotation matrix to 4d quaternion vector.\n    The quaternion vector has components in (x, y, z, w) format.\n\n    Args:\n        rotation_matrix (torch.Tensor): the rotation matrix to convert.\n        eps (float): small value to avoid zero division. Default: 1e-8.\n\n    Return:\n        torch.Tensor: the rotation in quaternion.\n\n    Shape:\n        - Input: :math:`(*, 3, 3)`\n        - Output: :math:`(*, 4)`\n\n    Example:\n        >>> input = torch.rand(4, 3, 3)  # Nx3x3\n        >>> output = rotation_matrix_to_quaternion(input)  # Nx4\n    '
    if (not isinstance(rotation_matrix, torch.Tensor)):
        raise TypeError('Input type is not a torch.Tensor. Got {}'.format(type(rotation_matrix)))
    if (not (rotation_matrix.shape[(- 2):] == (3, 3))):
        raise ValueError('Input size must be a (*, 3, 3) tensor. Got {}'.format(rotation_matrix.shape))

    def safe_zero_division(numerator: torch.Tensor, denominator: torch.Tensor) -> torch.Tensor:
        eps: float = torch.finfo(numerator.dtype).tiny
        return (numerator / torch.clamp(denominator, min=eps))
    rotation_matrix_vec: torch.Tensor = rotation_matrix.view(*rotation_matrix.shape[:(- 2)], 9)
    (m00, m01, m02, m10, m11, m12, m20, m21, m22) = torch.chunk(rotation_matrix_vec, chunks=9, dim=(- 1))
    trace: torch.Tensor = ((m00 + m11) + m22)

    def trace_positive_cond():
        sq = (torch.sqrt((trace + 1.0)) * 2.0)
        qw = (0.25 * sq)
        qx = safe_zero_division((m21 - m12), sq)
        qy = safe_zero_division((m02 - m20), sq)
        qz = safe_zero_division((m10 - m01), sq)
        return torch.cat([qx, qy, qz, qw], dim=(- 1))

    def cond_1():
        sq = (torch.sqrt(((((1.0 + m00) - m11) - m22) + eps)) * 2.0)
        qw = safe_zero_division((m21 - m12), sq)
        qx = (0.25 * sq)
        qy = safe_zero_division((m01 + m10), sq)
        qz = safe_zero_division((m02 + m20), sq)
        return torch.cat([qx, qy, qz, qw], dim=(- 1))

    def cond_2():
        sq = (torch.sqrt(((((1.0 + m11) - m00) - m22) + eps)) * 2.0)
        qw = safe_zero_division((m02 - m20), sq)
        qx = safe_zero_division((m01 + m10), sq)
        qy = (0.25 * sq)
        qz = safe_zero_division((m12 + m21), sq)
        return torch.cat([qx, qy, qz, qw], dim=(- 1))

    def cond_3():
        sq = (torch.sqrt(((((1.0 + m22) - m00) - m11) + eps)) * 2.0)
        qw = safe_zero_division((m10 - m01), sq)
        qx = safe_zero_division((m02 + m20), sq)
        qy = safe_zero_division((m12 + m21), sq)
        qz = (0.25 * sq)
        return torch.cat([qx, qy, qz, qw], dim=(- 1))
    where_2 = torch.where((m11 > m22), cond_2(), cond_3())
    where_1 = torch.where(((m00 > m11) & (m00 > m22)), cond_1(), where_2)
    quaternion: torch.Tensor = torch.where((trace > 0.0), trace_positive_cond(), where_1)
    return quaternion