code: public static double perfectAUC( Vec vprob, Vec vacts ) {
      if( vacts.min() < 0 || vacts.max() > 1 || !vacts.isInt() )
        throw new IllegalArgumentException("Actuals are either 0 or 1");
      if( vprob.min() < 0 || vprob.max() > 1 )
        throw new IllegalArgumentException("Probabilities are between 0 and 1");
      // Horrible data replication into array of structs, to sort.  
      Pair[] ps = new Pair[(int)vprob.length()];
      Vec.Reader rprob = vprob.new Reader();
      Vec.Reader racts = vacts.new Reader();
      for( int i=0; i<ps.length; i++ )
        ps[i] = new Pair(rprob.at(i),(byte)racts.at8(i));
      return perfectAUC(ps);
    }
docs: small data (probably caps out at about 10M rows).