# Path: third_party/xiuminglib/xiuminglib/linalg.py
# def normalize(vecs, axis=0):
#     """Normalizes vectors.
# 
#     Args:
#         vecs (array_like): 1D array for a single vector, 2D array for multiple
#             vectors, 3D array for an "image" of vectors, etc.
#         axis (int, optional): Along which axis normalization is done.
# 
#     Returns:
#         numpy.ndarray: Normalized vector(s) of the same shape as input.
#     """
#     vecs = np.array(vecs)
# 
#     if axis < 0:
#         raise ValueError("Negative index not allowed for safety")
#     n_dims = vecs.ndim
#     if axis >= n_dims:
#         raise ValueError((
#             "Can't normalize along axis %d when you only have %d dimension(s)"
#         ) % (axis, n_dims))
# 
#     norms = np.linalg.norm(vecs, axis=axis)
#     if (norms == 0.).any():
#         raise ValueError("Found zero-norm vectors")
# 
#     broadcastable = list(vecs.shape)
#     broadcastable[axis] = 1
#     vecs_normalized = np.divide(vecs, norms.reshape(broadcastable))
# 
#     return vecs_normalized
# 
# Path: third_party/xiuminglib/xiuminglib/log.py
# def get_logger(level=None):
#     """Creates a logger for functions in the library.
# 
#     Args:
#         level (str, optional): Logging level. Defaults to ``logging.INFO``.
# 
#     Returns:
#         logging.Logger: Logger created.
#     """
#     if level is None:
#         level = logging.INFO
#     logging.basicConfig(level=level)
#     logger = logging.getLogger()
#     return logger


import math
import numpy as np
from ..linalg import normalize
from ..log import get_logger


def _warn_degree(angles):
    if (np.abs(angles) > 2 * np.pi).any():
        logger.warning((
            "Some input value falls outside [-2pi, 2pi]. You sure inputs are "
            "in radians"))


def axis_angle_to_rot_mat(axis, theta):
    r"""Gets rotation matrix that rotates points around an arbitrary axis by any
    angle.

    Rotating around the :math:`x`/:math:`y`/:math:`z` axis are special cases of
    this, where you simply specify the axis to be one of those axes.

    Args:
        axis (array_like): 3-vector that specifies the end point of the
            rotation axis (start point is the origin). This will be normalized
            to be unit-length.
        theta (float): Angle in radians, prescribed by the right-hand rule, so
            a negative value means flipping the rotation axis.

    Returns:
        numpy.ndarray: :math:`3\times 3` rotation matrix, to be pre-multiplied
        with the vector to rotate.
    """
    # NOTE: not tested thoroughly. Use with caution!
    axis = np.array(axis)


# Path: third_party/xiuminglib/xiuminglib/linalg.py
# def normalize(vecs, axis=0):
#     """Normalizes vectors.
# 
#     Args:
#         vecs (array_like): 1D array for a single vector, 2D array for multiple
#             vectors, 3D array for an "image" of vectors, etc.
#         axis (int, optional): Along which axis normalization is done.
# 
#     Returns:
#         numpy.ndarray: Normalized vector(s) of the same shape as input.
#     """
#     vecs = np.array(vecs)
# 
#     if axis < 0:
#         raise ValueError("Negative index not allowed for safety")
#     n_dims = vecs.ndim
#     if axis >= n_dims:
#         raise ValueError((
#             "Can't normalize along axis %d when you only have %d dimension(s)"
#         ) % (axis, n_dims))
# 
#     norms = np.linalg.norm(vecs, axis=axis)
#     if (norms == 0.).any():
#         raise ValueError("Found zero-norm vectors")
# 
#     broadcastable = list(vecs.shape)
#     broadcastable[axis] = 1
#     vecs_normalized = np.divide(vecs, norms.reshape(broadcastable))
# 
#     return vecs_normalized
# 
# Path: third_party/xiuminglib/xiuminglib/log.py
# def get_logger(level=None):
#     """Creates a logger for functions in the library.
# 
#     Args:
#         level (str, optional): Logging level. Defaults to ``logging.INFO``.
# 
#     Returns:
#         logging.Logger: Logger created.
#     """
#     if level is None:
#         level = logging.INFO
#     logging.basicConfig(level=level)
#     logger = logging.getLogger()
#     return logger


# Path: third_party/xiuminglib/xiuminglib/geometry/rot.py
import math
import numpy as np
from ..linalg import normalize
from ..log import get_logger



def _warn_degree(angles):
    if (np.abs(angles) > 2 * np.pi).any():
        logger.warning((
            "Some input value falls outside [-2pi, 2pi]. You sure inputs are "
            "in radians"))


def axis_angle_to_rot_mat(axis, theta):
    r"""Gets rotation matrix that rotates points around an arbitrary axis by any
    angle.

    Rotating around the :math:`x`/:math:`y`/:math:`z` axis are special cases of
    this, where you simply specify the axis to be one of those axes.

    Args:
        axis (array_like): 3-vector that specifies the end point of the
            rotation axis (start point is the origin). This will be normalized
            to be unit-length.
        theta (float): Angle in radians, prescribed by the right-hand rule, so
            a negative value means flipping the rotation axis.

    Returns:
        numpy.ndarray: :math:`3\times 3` rotation matrix, to be pre-multiplied
        with the vector to rotate.
    """
    # NOTE: not tested thoroughly. Use with caution!
    axis = np.array(axis)


    ux, uy, uz = normalize(axis)