docs: private void calculateCL(double[] x) {
      if (values != null) {
        rvfcalculate(x);
        return;
      }
      //System.out.println("Checking at: "+x[0]+" "+x[1]+" "+x[2]);
      value = 0.0;
      if (derivative == null) {
        derivative = new double[x.length];
      } else {
        Arrays.fill(derivative, 0.0);
      }
  
      if (derivativeNumerator == null) {
        derivativeNumerator = new double[x.length];
        //use dataIterable if data is null & vice versa
        if(data != null) {
          for (int d = 0; d < data.length; d++) {
            //         if (d == testMin) {
            //           d = testMax - 1;
            //           continue;
            //         }
            int[] features = data[d];
            for (int f = 0; f < features.length; f++) {
              int i = indexOf(features[f], labels[d]);
              if (dataweights == null) {
                derivativeNumerator[i] -= 1;
              } else {
                derivativeNumerator[i] -= dataweights[d];
              }
            }
          }
        }
        //TODO: Make sure this work as expected!!
        else if(dataIterable != null) {
          //int index = 0;
          for (Datum<L, F> datum : dataIterable) {
            //         if (d == testMin) {
            //           d = testMax - 1;
            //           continue;
            //         }
            Collection<F> features = datum.asFeatures();
            for (F feature : features) {
              int i = indexOf(featureIndex.indexOf(feature), labelIndex.indexOf(datum.label()));
              if (dataweights == null) {
                derivativeNumerator[i] -= 1;
              } /*else {
                derivativeNumerator[i] -= dataweights[index];
              }*/
            }
          }
        }
        else {
          System.err.println("Both were null!  Couldn't calculate.");
          System.exit(-1);
        }
      }
      copy(derivative, derivativeNumerator);
      //    Arrays.fill(derivative, 0.0);
      double[] sums = new double[numClasses];
      double[] probs = new double[numClasses];
      //    double[] counts = new double[numClasses];
      //    Arrays.fill(counts, 0.0);
      
      Iterator<Datum<L, F>> iter = null;
      int d = -1;
      if(useIterable)
        iter = dataIterable.iterator();
      Datum<L, F> datum = null;
      while(true){
        if(useIterable) {
          if(!iter.hasNext()) break;
          datum = iter.next();
        } else {
          d++;
          if(d >= data.length) break;
        }
  
        //       if (d == testMin) {
        //         d = testMax - 1;
        //         continue;
        //       }
  
        // activation
        Arrays.fill(sums, 0.0);
        double total = 0;
        if(!useIterable) {
          int[] featuresArr = data[d];
  
          for (int c = 0; c < numClasses; c++) {
            for (int f = 0; f < featuresArr.length; f++) {
              int i = indexOf(featuresArr[f], c);
              sums[c] += x[i];
            }
          }
          // expectation (slower routine replaced by fast way)
          // double total = Double.NEGATIVE_INFINITY;
          // for (int c=0; c<numClasses; c++) {
          //   total = SloppyMath.logAdd(total, sums[c]);
          // }
          total = ArrayMath.logSum(sums);
          for (int c = 0; c < numClasses; c++) {
            probs[c] = Math.exp(sums[c] - total);
            if (dataweights != null) {
              probs[c] *= dataweights[d];
            }
            for (int f = 0; f < featuresArr.length; f++) {
              int i = indexOf(featuresArr[f], c);
              derivative[i] += probs[c];
            }
          }
        } else {
          Collection<F> features = datum.asFeatures();
          for (int c = 0; c < numClasses; c++) {
            for (F feature : features) {
              int i = indexOf(featureIndex.indexOf(feature), c);
              sums[c] += x[i];
            }
          }
          // expectation (slower routine replaced by fast way)
          // double total = Double.NEGATIVE_INFINITY;
          // for (int c=0; c<numClasses; c++) {
          //   total = SloppyMath.logAdd(total, sums[c]);
          // }
          total = ArrayMath.logSum(sums);
          for (int c = 0; c < numClasses; c++) {
            probs[c] = Math.exp(sums[c] - total);
            if (dataweights != null) {
              probs[c] *= dataweights[d];
            }
            for (F feature : features) {
              int i = indexOf(featureIndex.indexOf(feature), c);
              derivative[i] += probs[c];
            }
          }
        }
  
        int labelindex;
        if(useIterable)
          labelindex = labelIndex.indexOf(datum.label());
        else 
          labelindex = labels[d];
        double dV = sums[labelindex] - total;
        if (dataweights != null) {
          dV *= dataweights[d];
        }
        value -= dV;
        
      }
      value += prior.compute(x, derivative);
    }