code: def gramian(self):
          
          if self.mode == 'spark':
              rdd = self.values.tordd()
  
              from pyspark.accumulators import AccumulatorParam
  
              class MatrixAccumulator(AccumulatorParam):
                  def zero(self, value):
                      return zeros(shape(value))
  
                  def addInPlace(self, val1, val2):
                      val1 += val2
                      return val1
  
              global mat
              init = zeros((self.shape[1], self.shape[1]))
              mat = rdd.context.accumulator(init, MatrixAccumulator())
  
              def outer_sum(x):
                  global mat
                  mat += outer(x, x)
  
              rdd.values().foreach(outer_sum)
              return self._constructor(mat.value, index=self.index)
  
          if self.mode == 'local':
              return self._constructor(dot(self.values.T, self.values), index=self.index)
docs: Compute gramian of a distributed matrix.
  
          The gramian is defined as the product of the matrix
          with its transpose, i.e. A^T * A.