# 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


import numpy as np
from ..linalg import normalize as normalize_vec
    normal = normal_map.reshape(-1, 3).T # 3-by-N

    normal_trans = rotmat.dot(normal)

    normal_map_trans = normal_trans.T.reshape(orig_shape)
    return normal_map_trans


def gen_world2local(normal):
    """Generates rotation matrices that transform world normals to local
    :math:`+z`, world tangents to local :math:`+x`, and world binormals to
    local :math:`+y`.

    Args:
        normal (numpy.ndarray): any size-by-3 array of normal vectors.

    Returns:
        numpy.ndarray: Any size-by-3-by-3 world-to-local rotation matrices,
        which should be left-multiplied to world coordinates.
    """
    last_dim_i = normal.ndim - 1

    z = np.array((0, 0, 1), dtype=float)

    # Tangents
    t = np.cross(normal, z)
    if (t == 0).all(axis=-1).any():
        raise ValueError((
            "Found (0, 0, 0) tangents! Possible reasons: normal colinear with "
            "(0, 0, 1); normal is (0, 0, 0)"))

# 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/geometry/normal.py
import numpy as np
from ..linalg import normalize as normalize_vec

    normal = normal_map.reshape(-1, 3).T # 3-by-N

    normal_trans = rotmat.dot(normal)

    normal_map_trans = normal_trans.T.reshape(orig_shape)
    return normal_map_trans


def gen_world2local(normal):
    """Generates rotation matrices that transform world normals to local
    :math:`+z`, world tangents to local :math:`+x`, and world binormals to
    local :math:`+y`.

    Args:
        normal (numpy.ndarray): any size-by-3 array of normal vectors.

    Returns:
        numpy.ndarray: Any size-by-3-by-3 world-to-local rotation matrices,
        which should be left-multiplied to world coordinates.
    """
    last_dim_i = normal.ndim - 1

    z = np.array((0, 0, 1), dtype=float)

    # Tangents
    t = np.cross(normal, z)
    if (t == 0).all(axis=-1).any():
        raise ValueError((
            "Found (0, 0, 0) tangents! Possible reasons: normal colinear with "
            "(0, 0, 1); normal is (0, 0, 0)"))

    t = normalize_vec(t, axis=last_dim_i)