code: def from_rotation_matrix(
      rotation_matrix: type_alias.TensorLike,
      name: str = "quaternion_from_rotation_matrix",
  ) -> tf.Tensor:
      """Converts a rotation matrix representation to a quaternion.
  
      Warning:
        This function is not smooth everywhere.
  
      Note:
        In the following, A1 to An are optional batch dimensions.
  
      Args:
        rotation_matrix: A tensor of shape `[A1, ..., An, 3, 3]`, where the last two
          dimensions represent a rotation matrix.
        name: A name for this op that defaults to "quaternion_from_rotation_matrix".
  
      Returns:
        A tensor of shape `[A1, ..., An, 4]`, where the last dimension represents
        a normalized quaternion.
  
      Raises:
        ValueError: If the shape of `rotation_matrix` is not supported.
      """
      with tf.name_scope(name):
          rotation_matrix = tf.convert_to_tensor(value=rotation_matrix)
  
          shape.check_static(
              tensor=rotation_matrix,
              tensor_name="rotation_matrix",
              has_rank_greater_than=1,
              has_dim_equals=((-1, 3), (-2, 3)),
          )
          rotation_matrix = (
              rotation_matrix_3d.assert_rotation_matrix_normalized(
                  rotation_matrix
              )
          )
  
          trace = tf.linalg.trace(rotation_matrix)
          eps_addition = asserts.select_eps_for_addition(
              rotation_matrix.dtype
          )
          rows = tf.unstack(rotation_matrix, axis=-2)
          entries = [tf.unstack(row, axis=-1) for row in rows]
  
          def tr_positive():
              sq = tf.sqrt(trace + 1.0) * 2.0  # sq = 4 * qw.
              qw = 0.25 * sq
              qx = safe_ops.safe_unsigned_div(
                  entries[2][1] - entries[1][2], sq
              )
              qy = safe_ops.safe_unsigned_div(
                  entries[0][2] - entries[2][0], sq
              )
              qz = safe_ops.safe_unsigned_div(
                  entries[1][0] - entries[0][1], sq
              )
              return tf.stack((qx, qy, qz, qw), axis=-1)
  
          def cond_1():
              sq = (
                  tf.sqrt(
                      1.0
                      + entries[0][0]
                      - entries[1][1]
                      - entries[2][2]
                      + eps_addition
                  )
                  * 2.0
              )  # sq = 4 * qx.
              qw = safe_ops.safe_unsigned_div(
                  entries[2][1] - entries[1][2], sq
              )
              qx = 0.25 * sq
              qy = safe_ops.safe_unsigned_div(
                  entries[0][1] + entries[1][0], sq
              )
              qz = safe_ops.safe_unsigned_div(
                  entries[0][2] + entries[2][0], sq
              )
              return tf.stack((qx, qy, qz, qw), axis=-1)
  
          def cond_2():
              sq = (
                  tf.sqrt(
                      1.0
                      + entries[1][1]
                      - entries[0][0]
                      - entries[2][2]
                      + eps_addition
                  )
                  * 2.0
              )  # sq = 4 * qy.
              qw = safe_ops.safe_unsigned_div(
                  entries[0][2] - entries[2][0], sq
              )
              qx = safe_ops.safe_unsigned_div(
                  entries[0][1] + entries[1][0], sq
              )
              qy = 0.25 * sq
              qz = safe_ops.safe_unsigned_div(
                  entries[1][2] + entries[2][1], sq
              )
              return tf.stack((qx, qy, qz, qw), axis=-1)
  
          def cond_3():
              sq = (
                  tf.sqrt(
                      1.0
                      + entries[2][2]
                      - entries[0][0]
                      - entries[1][1]
                      + eps_addition
                  )
                  * 2.0
              )  # sq = 4 * qz.
              qw = safe_ops.safe_unsigned_div(
                  entries[1][0] - entries[0][1], sq
              )
              qx = safe_ops.safe_unsigned_div(
                  entries[0][2] + entries[2][0], sq
              )
              qy = safe_ops.safe_unsigned_div(
                  entries[1][2] + entries[2][1], sq
              )
              qz = 0.25 * sq
              return tf.stack((qx, qy, qz, qw), axis=-1)
  
          def cond_idx(cond):
              cond = tf.expand_dims(cond, -1)
              cond = tf.tile(
                  cond, [1] * (rotation_matrix.shape.ndims - 2) + [4]
              )
              return cond
  
          where_2 = tf.where(
              cond_idx(entries[1][1] > entries[2][2]),
              cond_2(),
              cond_3(),
          )
          where_1 = tf.where(
              cond_idx(
                  (entries[0][0] > entries[1][1])
                  & (entries[0][0] > entries[2][2])
              ),
              cond_1(),
              where_2,
          )
          quat = tf.where(cond_idx(trace > 0), tr_positive(), where_1)
          return quat
  
imports: from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  from typing import List
  from six.moves import range
  import tensorflow
  from tensorflow_graphics.geometry.transformation import rotation_matrix_3d
  from tensorflow_graphics.math import vector
  from tensorflow_graphics.util import asserts
  from tensorflow_graphics.util import export_api
  from tensorflow_graphics.util import safe_ops
  from tensorflow_graphics.util import shape
  from tensorflow_graphics.util import type_alias
label_desc: Use image node_id 7 for calling a global function with example usage: from_rotation_matrix(rotation_matrix, name) and returns: quat, tf, tf, tf, tf, cond