docs: public void iterateSample(Word2VecParam param, VocabWord w1, VocabWord w2, double alpha,
                      List<Triple<Integer, Integer, Integer>> changed) {
          if (w2 == null || w2.getIndex() < 0 || w1.getIndex() == w2.getIndex() || w1.getWord().equals("STOP")
                          || w2.getWord().equals("STOP") || w1.getWord().equals("UNK") || w2.getWord().equals("UNK"))
              return;
          int vectorLength = param.getVectorLength();
          InMemoryLookupTable weights = param.getWeights();
          boolean useAdaGrad = param.isUseAdaGrad();
          double negative = param.getNegative();
          INDArray table = param.getTable();
          double[] expTable = param.getExpTable().getValue();
          double MAX_EXP = 6;
          int numWords = param.getNumWords();
          //current word vector
          INDArray l1 = weights.vector(w2.getWord());
  
  
          //error for current word and context
          INDArray neu1e = Nd4j.create(vectorLength);
  
          for (int i = 0; i < w1.getCodeLength(); i++) {
              int code = w1.getCodes().get(i);
              int point = w1.getPoints().get(i);
  
              INDArray syn1 = weights.getSyn1().slice(point);
  
              double dot = Nd4j.getBlasWrapper().level1().dot(syn1.length(), 1.0, l1, syn1);
  
              if (dot < -MAX_EXP || dot >= MAX_EXP)
                  continue;
  
              int idx = (int) ((dot + MAX_EXP) * ((double) expTable.length / MAX_EXP / 2.0));
  
              //score
              double f = expTable[idx];
              //gradient
              double g = (1 - code - f) * (useAdaGrad ? w1.getGradient(i, alpha, alpha) : alpha);
  
  
              Nd4j.getBlasWrapper().level1().axpy(syn1.length(), g, syn1, neu1e);
              Nd4j.getBlasWrapper().level1().axpy(syn1.length(), g, l1, syn1);
  
  
              changed.add(new Triple<>(point, w1.getIndex(), -1));
  
          }
  
  
          changed.add(new Triple<>(w1.getIndex(), w2.getIndex(), -1));
          //negative sampling
          if (negative > 0) {
              int target = w1.getIndex();
              int label;
              INDArray syn1Neg = weights.getSyn1Neg().slice(target);
  
              for (int d = 0; d < negative + 1; d++) {
                  if (d == 0) {
  
                      label = 1;
                  } else {
                      nextRandom.set(nextRandom.get() * 25214903917L + 11);
                      // FIXME: int cast
                      target = table.getInt((int) (nextRandom.get() >> 16) % (int) table.length());
                      if (target == 0)
                          target = (int) nextRandom.get() % (numWords - 1) + 1;
                      if (target == w1.getIndex())
                          continue;
                      label = 0;
                  }
  
                  double f = Nd4j.getBlasWrapper().dot(l1, syn1Neg);
                  double g;
                  if (f > MAX_EXP)
                      g = useAdaGrad ? w1.getGradient(target, (label - 1), alpha) : (label - 1) * alpha;
                  else if (f < -MAX_EXP)
                      g = label * (useAdaGrad ? w1.getGradient(target, alpha, alpha) : alpha);
                  else
                      g = useAdaGrad ? w1
                                      .getGradient(target,
                                                      label - expTable[(int) ((f + MAX_EXP)
                                                                      * (expTable.length / MAX_EXP / 2))],
                                                      alpha)
                                      : (label - expTable[(int) ((f + MAX_EXP) * (expTable.length / MAX_EXP / 2))])
                                                      * alpha;
                  Nd4j.getBlasWrapper().level1().axpy(l1.length(), g, neu1e, l1);
  
                  Nd4j.getBlasWrapper().level1().axpy(l1.length(), g, syn1Neg, l1);
  
                  changed.add(new Triple<>(-1, -1, label));
  
              }
          }
  
  
          Nd4j.getBlasWrapper().level1().axpy(l1.length(), 1.0f, neu1e, l1);
  
  
      }