private static int GetContainer(int contained, IndexedBitMatrix contains)
 {
     int n = contains.RowCount;
     for (int i = 0; i < n; i++){
         if (contains.Get(i, contained)){
             return i;
         }
     }
     return -1;
 }
 private static void ClusterRows(ref int[][] rowInds, ref string[][] geneIds)
 {
     int n = rowInds.Length;
     for (int i = 0; i < n; i++){
         Array.Sort(geneIds[i]);
     }
     IndexedBitMatrix contains = new IndexedBitMatrix(n, n);
     for (int i = 0; i < n; i++){
         for (int j = 0; j < n; j++){
             if (i == j){
                 continue;
             }
             contains.Set(i, j, Contains(geneIds[i], geneIds[j]));
         }
     }
     int count;
     do{
         count = 0;
         int start = 0;
         while (true){
             int container = -1;
             int contained = -1;
             for (int i = start; i < rowInds.Length; i++){
                 container = GetContainer(i, contains);
                 if (container != -1){
                     contained = i;
                     break;
                 }
             }
             if (container == -1){
                 break;
             }
             for (int i = 0; i < n; i++){
                 contains.Set(i, contained, false);
                 contains.Set(contained, i, false);
             }
             geneIds[contained] = new string[0];
             rowInds[container] = ArrayUtils.Concat(rowInds[container], rowInds[contained]);
             rowInds[contained] = new int[0];
             start = contained + 1;
             count++;
         }
     } while (count > 0);
     List<int> valids = new List<int>();
     for (int i = 0; i < n; i++){
         if (geneIds[i].Length > 0){
             valids.Add(i);
         }
     }
     int[] a = valids.ToArray();
     rowInds = ArrayUtils.SubArray(rowInds, a);
     geneIds = ArrayUtils.SubArray(geneIds, a);
 }