docs: protected void computeGradient(AffinityMatrix pij, double[][] qij, double qij_isum, double[][] sol, double[] meta) {
      final int dim3 = dim * 3;
      int size = pij.size();
      for(int i = 0, off = 0; i < size; i++, off += dim3) {
        final double[] sol_i = sol[i], qij_i = qij[i];
        Arrays.fill(meta, off, off + dim, 0.); // Clear gradient only
        for(int j = 0; j < size; j++) {
          if(i == j) {
            continue;
          }
          final double[] sol_j = sol[j];
          final double qij_ij = qij_i[j];
          // Qij after scaling!
          final double q = MathUtil.max(qij_ij * qij_isum, MIN_QIJ);
          double a = 4 * (pij.get(i, j) - q); // SNE gradient
          for(int k = 0; k < dim; k++) {
            meta[off + k] += a * (sol_i[k] - sol_j[k]);
          }
        }
      }
    }