code: protected double kEval(int a, int b)
      {
          if(cacheMode == CacheMode.FULL)
          {
              if(a > b)
              {
                  int tmp = a;
                  a = b;
                  b = tmp;
              }
  
              double val = fullCache[a][b-a];
              if(Double.isNaN(val))//lazy init
                  return fullCache[a][b-a] = k(a, b);
              return val;
          }
          else if(cacheMode == CacheMode.ROWS)
          {
              double[] cache;
              if(specific_row_cache_row == a)
                  cache = specific_row_cache_values;
              else
                  cache = partialCache.get(a);
              if (cache == null)//not present
              {
                  //make a row
                  cache = new double[vecs.size()];
                  Arrays.fill(cache, Double.NaN);
  
                  double[] cache_missed = partialCache.putIfAbsentAndGet(a, cache);
                  if(cache_missed != null)
                      cache = cache_missed;
  
                  if (Double.isNaN(cache[b]))
                      return cache[b] = k(a, b);
                  else
                      return cache[b];
  
              }
          }
          return k(a, b);
      }
docs: Performs a kernel evaluation of the a'th and b'th vectors in the
  {@link #vecs} array.
  
  @param a the first vector index
  @param b the second vector index
  @return the kernel evaluation of k(a, b)