class_docstr: Private class for the n-dimensional hypersphere.
  
  Class for the n-dimensional hypersphere embedded in the
  (n+1)-dimensional Euclidean space.
  
  By default, points are parameterized by their extrinsic
  (n+1)-coordinates. For dimensions 1 and 2, this can be changed with the
  `default_coords_type` parameter. For dimensions 1 (the circle),
  the intrinsic coordinates correspond angles in radians, with 0. mapping
  to point [1., 0.]. For dimension 2, the intrinsic coordinates are the
  spherical coordinates from the north pole, i.e. where angles [0., 0.]
  correspond to point [0., 0., 1.].
  
  Parameters
  ----------
  dim : int
      Dimension of the hypersphere.
  
  default_coords_type : str, {'extrinsic', 'intrinsic'}
      Type of representation for dimensions 1 and 2.
docstr: Sample from the Riemannian normal distribution.
  
  The Riemannian normal distribution, or spherical normal in this case,
  is defined by the probability density function (with respect to the
  Riemannian volume measure) proportional to:
  
  .. math::
          \exp \Big \left(- \frac{\lambda}{2} \mathtm{arccos}^2(x^T\mu)
          \Big \right)
  
  where :math:`\mu` is the mean and :math:`\lambda` is the isotropic
  precision. For the anisotropic case,
  :math:`\log_{\mu}(x)^T \Lambda \log_{\mu}(x)` is used instead.
  
  A rejection algorithm is used to sample from this distribution [Hau18]_
  
  Parameters
  ----------
  mean : array-like, shape=[dim]
      Mean parameter of the distribution.
      Optional, default: (0,...,0,1) (the north pole).
  precision : float or array-like, shape=[dim, dim]
      Inverse of the covariance parameter of the normal distribution.
      If a float is passed, the covariance matrix is precision times
      identity.
      Optional, default: identity.
  n_samples : int
      Number of samples.
      Optional, default: 1.
  max_iter : int
      Maximum number of trials in the rejection algorithm. In case it
      is reached, the current number of samples < n_samples is returned.
      Optional, default: 100.
  
  Returns
  -------
  point : array-like, shape=[n_samples, dim + 1]
      Points sampled on the sphere.
  
  References
  ----------
  .. [Hau18]  Hauberg, Soren. “Directional Statistics with the
              Spherical Normal Distribution.”
              In 2018 21st International Conference on Information
              Fusion (FUSION), 704–11, 2018.
              https://doi.org/10.23919/ICIF.2018.8455242.
docstr_tok: ["Sample","from","the","Riemannian","normal","distribution",".","The","Riemannian","normal","distribution",",","or","spherical","normal","in","this","case",",","is","defined","by","the","probability","density","function","(","with","respect","to","the","Riemannian","volume","measure",")","proportional","to",":","..","math",":",":","\\exp","\\Big","\\left","(","-","\\frac","{","\\lambda","}","{","2","}","\\mathtm","{","arccos","}","^2","(","x^T\\mu",")","\\Big","\\right",")","where",":","math",":","`","\\mu","`","is","the","mean","and",":","math",":","`","\\lambda","`","is","the","isotropic","precision",".","For","the","anisotropic","case",",",":","math",":","`","\\log_","{","\\mu","}","(","x",")","^T","\\Lambda","\\log_","{","\\mu","}","(","x",")","`","is","used","instead",".","A","rejection","algorithm","is","used","to","sample","from","this","distribution","[","Hau18","]","_","Parameters","--","--","--","--","--","mean",":","array-like",",","shape=","[","dim","]","Mean","parameter","of","the","distribution",".","Optional",",","default",":","(","0",",","...",",0,1",")","(","the","north","pole",")",".","precision",":","float","or","array-like",",","shape=","[","dim",",","dim","]","Inverse","of","the","covariance","parameter","of","the","normal","distribution",".","If","a","float","is","passed",",","the","covariance","matrix","is","precision","times","identity",".","Optional",",","default",":","identity",".","n_samples",":","int","Number","of","samples",".","Optional",",","default",":","1.","max_iter",":","int","Maximum","number","of","trials","in","the","rejection","algorithm",".","In","case","it","is","reached",",","the","current","number","of","samples","<","n_samples","is","returned",".","Optional",",","default",":","100",".","Returns","--","--","--","-","point",":","array-like",",","shape=","[","n_samples",",","dim","+","1","]","Points","sampled","on","the","sphere",".","References","--","--","--","--","--","..","[","Hau18","]","Hauberg",",","Soren",".","\u201c","Directional","Statistics","with","the","Spherical","Normal","Distribution.","\u201d","In","2018","21st","International","Conference","on","Information","Fusion","(","FUSION",")",",","704\u201311",",","2018.","https",":","\/\/doi.org\/10.23919\/ICIF.2018.8455242","."]
code: def random_riemannian_normal(
      self, mean=None, precision=None, n_samples=1, max_iter=100
  ):
      r"""Sample from the Riemannian normal distribution.
  
      The Riemannian normal distribution, or spherical normal in this case,
      is defined by the probability density function (with respect to the
      Riemannian volume measure) proportional to:
  
      .. math::
              \exp \Big \left(- \frac{\lambda}{2} \mathtm{arccos}^2(x^T\mu)
              \Big \right)
  
      where :math:`\mu` is the mean and :math:`\lambda` is the isotropic
      precision. For the anisotropic case,
      :math:`\log_{\mu}(x)^T \Lambda \log_{\mu}(x)` is used instead.
  
      A rejection algorithm is used to sample from this distribution [Hau18]_
  
      Parameters
      ----------
      mean : array-like, shape=[dim]
          Mean parameter of the distribution.
          Optional, default: (0,...,0,1) (the north pole).
      precision : float or array-like, shape=[dim, dim]
          Inverse of the covariance parameter of the normal distribution.
          If a float is passed, the covariance matrix is precision times
          identity.
          Optional, default: identity.
      n_samples : int
          Number of samples.
          Optional, default: 1.
      max_iter : int
          Maximum number of trials in the rejection algorithm. In case it
          is reached, the current number of samples < n_samples is returned.
          Optional, default: 100.
  
      Returns
      -------
      point : array-like, shape=[n_samples, dim + 1]
          Points sampled on the sphere.
  
      References
      ----------
      .. [Hau18]  Hauberg, Soren. “Directional Statistics with the
                  Spherical Normal Distribution.”
                  In 2018 21st International Conference on Information
                  Fusion (FUSION), 704–11, 2018.
                  https://doi.org/10.23919/ICIF.2018.8455242.
      """
      dim = self.dim
      n_accepted, n_iter = 0, 0
      result = []
      if precision is None:
          precision_ = gs.eye(self.dim)
      elif isinstance(precision, (float, int)):
          precision_ = precision * gs.eye(self.dim)
      else:
          precision_ = precision
      precision_2 = precision_ + (dim - 1) / gs.pi * gs.eye(dim)
      tangent_cov = gs.linalg.inv(precision_2)
  
      def threshold(random_v):
          """Compute the acceptance threshold."""
          squared_norm = gs.sum(random_v**2, axis=-1)
          sinc = utils.taylor_exp_even_func(
              squared_norm, utils.sinc_close_0
          ) ** (dim - 1)
          threshold_val = sinc * gs.exp(
              squared_norm * (dim - 1) / 2 / gs.pi
          )
          return threshold_val, squared_norm**0.5
  
      while (n_accepted < n_samples) and (n_iter < max_iter):
          envelope = gs.random.multivariate_normal(
              gs.zeros(dim), tangent_cov, size=(n_samples - n_accepted,)
          )
          thresh, norm = threshold(envelope)
          proposal = gs.random.rand(n_samples - n_accepted)
          criterion = gs.logical_and(norm <= gs.pi, proposal <= thresh)
          result.append(envelope[criterion])
          n_accepted += gs.sum(criterion)
          n_iter += 1
      if n_accepted < n_samples:
          logging.warning(
              "Maximum number of iteration reached in rejection "
              "sampling before n_samples were accepted."
          )
      tangent_sample_intr = gs.concatenate(result)
      tangent_sample = gs.concatenate(
          [tangent_sample_intr, gs.zeros(n_accepted)[:, None]], axis=1
      )
  
      north_pole = gs.array([0.0] * dim + [1.0])
      if mean is not None:
          mean_from_north = self.metric.log(mean, north_pole)
          tangent_sample_at_pt = self.metric.parallel_transport(
              tangent_sample, north_pole, mean_from_north
          )
      else:
          tangent_sample_at_pt = tangent_sample
          mean = north_pole
      sample = self.metric.exp(tangent_sample_at_pt, mean)
      return sample[0] if (n_samples == 1) else sample
  
imports: import logging
  import math
  from itertools import product
  from scipy.stats import beta
  import geomstats.algebra_utils
  import geomstats.backend
  from geomstats.geometry.base import LevelSet
  from geomstats.geometry.euclidean import Euclidean
  from geomstats.geometry.riemannian_metric import RiemannianMetric
  from geomstats.vectorization import get_batch_shape, repeat_out
label_desc: Use image node_id 20 for calling the _Hypersphere obj's underlying member method code with example usage: obj.random_riemannian_normal(mean, precision, n_samples, max_iter) and returns: unknown, threshold_val,  unknown