class_docstr: Class that defines operations using a Poincare ball.
class_docstr_tok: ["Class","that","defines","operations","using","a","Poincare","ball","."]
docstr: Compute the Mobius addition of two points.
  
  The Mobius addition is useful to compute the log and exp in the
  'ball' representation.
  
  .. math::
  
      a\oplus b=\frac{(1+2\langle a,b\rangle + ||b||^2)a+
      (1-||a||^2)b}{1+2\langle a,b\rangle + ||a||^2||b||^2}
  
  Parameters
  ----------
  point_a : array-like, shape=[..., dim]
      Point in Poincare ball.
  point_b : array-like, shape=[..., dim]
      Point in Poincare ball.
  project_first : boolean
      Project points on the ball or not (according to tolerance).
  
  Returns
  -------
  mobius_add : array-like, shape=[..., dim]
      Result of the Mobius addition.
docstr_tok: ["Compute","the","Mobius","addition","of","two","points",".","The","Mobius","addition","is","useful","to","compute","the","log","and","exp","in","the","'ball","'","representation",".","..","math",":",":","a\\oplus","b=\\frac","{","(","1+2\\langle","a",",","b\\rangle","+","||b||^2",")","a+","(","1-||a||^2",")","b","}","{","1+2\\langle","a",",","b\\rangle","+","||a||^2||b||^2","}","Parameters","--","--","--","--","--","point_a",":","array-like",",","shape=","[","...",",","dim","]","Point","in","Poincare","ball",".","point_b",":","array-like",",","shape=","[","...",",","dim","]","Point","in","Poincare","ball",".","project_first",":","boolean","Project","points","on","the","ball","or","not","(","according","to","tolerance",")",".","Returns","--","--","--","-","mobius_add",":","array-like",",","shape=","[","...",",","dim","]","Result","of","the","Mobius","addition","."]
code: def mobius_add(self, point_a, point_b, project_first=True):
      r"""Compute the Mobius addition of two points.
  
      The Mobius addition is useful to compute the log and exp in the
      'ball' representation.
  
      .. math::
  
          a\oplus b=\frac{(1+2\langle a,b\rangle + ||b||^2)a+
          (1-||a||^2)b}{1+2\langle a,b\rangle + ||a||^2||b||^2}
  
      Parameters
      ----------
      point_a : array-like, shape=[..., dim]
          Point in Poincare ball.
      point_b : array-like, shape=[..., dim]
          Point in Poincare ball.
      project_first : boolean
          Project points on the ball or not (according to tolerance).
  
      Returns
      -------
      mobius_add : array-like, shape=[..., dim]
          Result of the Mobius addition.
      """
      if project_first:
          point_a = self._space.projection(point_a)
          point_b = self._space.projection(point_b)
      else:
          point_a_belong = self._space.belongs(point_a)
          point_b_belong = self._space.belongs(point_b)
  
          if not gs.all(point_a_belong) or not gs.all(point_b_belong):
              raise ValueError(
                  "Points do not belong to the Poincare ball"
              )
  
      inner = gs.sum(point_a * point_b, axis=-1)
      squared_norm_a = gs.sum(point_a**2, axis=-1)
      squared_norm_b = gs.sum(point_b**2, axis=-1)
      num_1 = gs.einsum(
          "...,...i->...i", 1 + 2 * inner + squared_norm_b, point_a
      )
      num_2 = gs.einsum("...,...i->...i", 1 - squared_norm_a, point_b)
      result = gs.einsum(
          "...,...i->...i",
          1.0 / (1 + 2 * inner + squared_norm_b * squared_norm_a),
          num_1 + num_2,
      )
      return self._space.projection(result)
  
imports: import math
  import geomstats.algebra_utils
  import geomstats.backend
  from geomstats.geometry._hyperbolic import _Hyperbolic
  from geomstats.geometry.base import VectorSpaceOpenSet
  from geomstats.geometry.euclidean import Euclidean
  from geomstats.geometry.riemannian_metric import RiemannianMetric
  from geomstats.vectorization import repeat_out
label_desc: Use image node_id 3 for calling the PoincareBallMetric obj's underlying member method code with example usage: obj.mobius_add(point_a, point_b, project_first) and returns: self