code: static double[] rank(int[] vals) {
          IntRank[] ranked = new IntRank[vals.length];
          for (int i = 0; i < vals.length; ++i)
              ranked[i] = new IntRank(vals[i], i);
          Arrays.sort(ranked);
              
          double[] ranks = new double[vals.length + 1];
          int correctionFactor = 0;
          
          for (int i = 0; i < ranked.length; ++i) {
              // Determine how many ties (if any) occur at this rank
              int ties = 0;
              for (int j = i + 1; j < ranked.length
                       && ranked[i].val == ranked[j].val; ++j, ++ties) 
                  ;
              if (ties == 0)
                  ranks[ranked[i].index] = i+1;
              else {
                  // Each tie is computed as the average of the ties' ranks, e.g.,
                  // two tie at rank 2 would be averaged as rank (2 + 3) / 2 = 2.5
                  double rank = i + 1 + (ties / 2d);
                  for (int j = i; j < i + ties + 1; ++j)
                      ranks[ranked[j].index] = rank;
                  // Skip to next non-tied value
                  i += ties;
  
                  // Change ties from the number of *additional* tied elements to
                  // the *total* number of tied elements when computing the
                  // correction factor.
                  ties += 1; 
                  correctionFactor += ((ties * ties * ties) - ties);
              }
          }
          ranks[ranks.length - 1] = correctionFactor;
          return ranks;
      }
docs: Computes the ranks of the values of {@code vals}, returning their ranks
  plus an addition array index representing the correction value when using
  the ranks to compute the correlation (see Eq. 9.6; p. 239 in
  Nonparametric Statistics for The Behavioral Sciences).