code: public static List<Integer> getSamplingPattern(int samplingLevel)
      {
          List<Integer> pattern = samplePatternCache.get(samplingLevel);
          if (pattern != null)
              return pattern;
  
          if (samplingLevel <= 1)
              return Arrays.asList(0);
  
          int[] odds = new int[samplingLevel / 2];
          int[] evens = new int[samplingLevel / 2];
          for (int i = 1; i < samplingLevel; i += 2)
              odds[i/2] = i;
          for (int i = 0; i < samplingLevel; i += 2)
              evens[i/2] = i;
  
          // especially for latter rounds, it's important that we spread out the start points, so we'll
          // make a recursive call to get an ordering for this list of start points
          List<Integer> ordering = getSamplingPattern(samplingLevel/2);
          List<Integer> startIndices = new ArrayList<>(samplingLevel);
  
          for (Integer index : ordering)
              startIndices.add(odds[index]);
          for (Integer index : ordering)
              startIndices.add(evens[index]);
  
          samplePatternCache.put(samplingLevel, startIndices);
          return startIndices;
      }
docs: Gets a list L of starting indices for downsampling rounds: the first round should start with the offset
  given by L[0], the second by the offset in L[1], etc.
  
  @param samplingLevel the base sampling level
  
  @return A list of `samplingLevel` unique indices between 0 and `samplingLevel`