Commit ece3ea42 authored by Dylan Aïssi's avatar Dylan Aïssi
Browse files

New upstream version 1.90~b6.1-180528

parent c271b712
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -93,7 +93,7 @@
static const char ver_str[] =
#ifdef STABLE_BUILD
  "PLINK v1.90b5.4"
  "PLINK v1.90b6.1"
#else
  "PLINK v1.90p"
#endif
@@ -105,7 +105,7 @@ static const char ver_str[] =
#else
  " 32-bit"
#endif
  " (10 Apr 2018)";
  " (28 May 2018)";
static const char ver_str2[] =
  // include leading space if day < 10, so character length stays the same
  ""
+5 −0
Original line number Diff line number Diff line
@@ -11236,6 +11236,11 @@ int32_t cmh_assoc(pthread_t* threads, FILE* bedfile, uintptr_t bed_offset, char*
              c_star = a1_ctd - a_star;
              d_star = ctrl_ctd - a1_ctd + a_star;

              // concordance fix (25 May 2018): print NA,NA instead of inf,0
              if ((a_star == 0.0) || (b_star == 0.0) || (c_star == 0.0) || (d_star == 0.0)) {
                goto cmh_assoc_bd_fail;
              }

	      // inverse variance
              dxx = 1.0 / a_star + 1.0 / b_star + 1.0 / c_star + 1.0 / d_star;

+19 −0
Original line number Diff line number Diff line
@@ -4902,6 +4902,25 @@ void cleanup_allele_storage(uint32_t max_allele_slen, uintptr_t allele_storage_e
  }
}

void cleanup_allele_storage2(uintptr_t allele_storage_entry_ct, char** allele_storage) {
  if (allele_storage) {
    const uintptr_t one_char_strs_addr = (uintptr_t)g_one_char_strs;
    for (uintptr_t idx = 0; idx < allele_storage_entry_ct;) {
      char* cur_entry = allele_storage[idx];
      if (!cur_entry) {
        // --merge-equal-pos hacked entry
        idx += 2;
        continue;
      }
      // take advantage of unsigned wraparound
      if ((((uintptr_t)cur_entry) - one_char_strs_addr) >= 512) {
	free(cur_entry);
      }
      ++idx;
    }
  }
}

void refresh_chrom_info(const Chrom_info* chrom_info_ptr, uintptr_t marker_uidx, uint32_t* __restrict chrom_end_ptr, uint32_t* __restrict chrom_fo_idx_ptr, uint32_t* __restrict is_x_ptr, uint32_t* __restrict is_y_ptr, uint32_t* __restrict is_mt_ptr, uint32_t* __restrict is_haploid_ptr) {
  // assumes we are at the end of the chromosome denoted by chrom_fo_idx.  Ok
  // for chrom_fo_idx == 0xffffffffU.
+4 −0
Original line number Diff line number Diff line
@@ -2266,6 +2266,10 @@ uint32_t allele_reset(const char* newval, uint32_t allele_slen, char** allele_pt

void cleanup_allele_storage(uint32_t max_allele_slen, uintptr_t allele_storage_entry_ct, char** allele_storage);

// needed by fixed --merge-equal-pos implementation, which takes more liberties
// with allele_storage[]
void cleanup_allele_storage2(uintptr_t allele_storage_entry_ct, char** allele_storage);

// no need for this; code is simpler if we just create a copy of marker_exclude
// with all non-autosomal loci removed
/*
+157 −91
Original line number Diff line number Diff line
@@ -5116,6 +5116,8 @@ int32_t incr_text_allele_str(char* allele_name, uint32_t an_len, Ll_str* allele_
  // Ll_str.next is a pointer to a linked list entry storing the next 1+ allele
  // names.  Worst case, the linked list is of length 4 (beyond that we error
  // out).  Most of the time, it'll be length 0.
  // Allele names are separated by tabs; \0 denotes the end of the allele name
  // list.
  // This type of function will become more important when it's time to parse
  // .vcf files, etc.
  uint32_t allele_num = 0;
@@ -5145,7 +5147,7 @@ int32_t incr_text_allele_str(char* allele_name, uint32_t an_len, Ll_str* allele_
    if ((slen == an_len) && (!memcmp(cur_allele_name_start, allele_name, an_len))) {
      marker_allele_cts[allele_num] += 1;
      return 0;
    } else {
    }
    allele_num++;
    if (cur_allele_name_start[slen] == '\t') {
      cur_allele_name_start = &(cur_allele_name_start[slen + 1]);
@@ -5170,7 +5172,6 @@ int32_t incr_text_allele_str(char* allele_name, uint32_t an_len, Ll_str* allele_
      return 0;
    }
  }
  }
  return RET_INVALID_FORMAT;
}
@@ -5443,22 +5444,17 @@ int32_t ped_to_bed_multichar_allele(FILE** pedfile_ptr, FILE** outfile_ptr, char
    }
    if (marker_allele_cts[4 * marker_idx + 2]) {
      uii = marker_allele_cts[4 * marker_idx + 3];
      if (map_is_unsorted) {
        sprintf(g_logbuf, "Warning: Variant %u (post-sort/filter) %sallelic; setting rarest missing.\n", map_reverse[marker_idx] + 1, (uii? "quad" : "tri"));
      } else {
        sprintf(g_logbuf, "Warning: Variant %" PRIuPTR " %sallelic; setting rarest alleles missing.\n", marker_idx + 1, (uii? "quad" : "tri"));
      }
      // bugfix (28 May 2018): do NOT look up map_reverse[] in unsorted case
      sprintf(g_logbuf, "Warning: Variant %" PRIuPTR "%s %sallelic; setting rarest missing.\n", marker_idx + 1, map_is_unsorted? " (post-sort)" : "", (uii? "quad" : "tri"));
      logerrprintb();
      get_top_two_ui(&(marker_allele_cts[4 * marker_idx]), uii? 4 : 3, &ulii, &uljj);
      uii = map_is_unsorted? map_reverse[marker_idx] : marker_idx;
    } else {
      ulii = (marker_allele_cts[4 * marker_idx] < marker_allele_cts[4 * marker_idx + 1])? 1 : 0;
      uljj = ulii ^ 1;
      uii = marker_idx;
    }
    aptr1 = get_llstr((Ll_str*)(&(marker_alleles_tmp[uii])), uljj);
    aptr2 = get_llstr((Ll_str*)(&(marker_alleles_tmp[uii])), ulii);
    aptr1 = get_llstr((Ll_str*)(&(marker_alleles_tmp[marker_idx])), uljj);
    aptr2 = get_llstr((Ll_str*)(&(marker_alleles_tmp[marker_idx])), ulii);
    if (!aptr1) {
      aptr1 = missing_geno_ptr;
    } else {
@@ -5708,7 +5704,7 @@ int32_t ped_to_bed_multichar_allele(FILE** pedfile_ptr, FILE** outfile_ptr, char
    g_bigstack_base -= cur_slen_rdup;
    logprint("\n");
    if (retval != RET_NOMEM) {
      LOGERRPRINTF("Error: More than 4 different alleles at variant %u%s.\n", uii + 1, map_is_unsorted? " (post-sort/filter)" : "");
      LOGERRPRINTF("Error: More than 4 different alleles at variant %u%s.\n", uii + 1, map_is_unsorted? " (post-sort)" : "");
    }
    break;
  ped_to_bed_multichar_allele_ret_INVALID_FORMAT_4:
@@ -6107,11 +6103,7 @@ int32_t ped_to_bed(char* pedname, char* mapname, char* outname, char* outname_en
	}
	if (marker_alleles[marker_idx * 4 + 2]) {
	  cc = marker_alleles[marker_idx * 4 + 3];
	  if (map_is_unsorted) {
	    sprintf(g_logbuf, "Warning: Variant %u (post-sort/filter) %sallelic; setting rarest missing.\n", map_reverse[marker_idx] + 1, (cc? "quad" : "tri"));
	  } else {
	    sprintf(g_logbuf, "Warning: Variant %" PRIuPTR " %sallelic; setting rarest alleles missing.\n", marker_idx + 1, (cc? "quad" : "tri"));
	  }
          sprintf(g_logbuf, "Warning: Variant %" PRIuPTR "%s %sallelic; setting rarest alleles missing.\n", marker_idx + 1, map_is_unsorted? " (post-sort)" : "", (cc? "quad" : "tri"));
	  logerrprintb();
	  ujj = (cc? 4 : 3);
	  // insertion sort
@@ -15021,8 +15013,8 @@ int32_t report_non_biallelics(char* outname, char* outname_end, Ll_str* non_bial
  return retval;
}
void merge_alleles_update_str(char* marker_allele_ptr, char** allele_ptrs, uint32_t* distinct_allele_ct_ptr) {
  uint32_t distinct_allele_ct = *distinct_allele_ct_ptr;
void merge_alleles_update_str(char* marker_allele_ptr, char** allele_ptrs, uint32_t* distinct_allele_ctp) {
  uint32_t distinct_allele_ct = *distinct_allele_ctp;
  uint32_t allele_idx = 0;
  if ((marker_allele_ptr == g_missing_geno_ptr) || (distinct_allele_ct == 3)) {
    return;
@@ -15033,33 +15025,52 @@ void merge_alleles_update_str(char* marker_allele_ptr, char** allele_ptrs, uint3
    }
    allele_idx++;
  }
  *distinct_allele_ct_ptr = distinct_allele_ct + 1;
  *distinct_allele_ctp = distinct_allele_ct + 1;
  if (distinct_allele_ct == 2) {
    return;
  }
  allele_ptrs[distinct_allele_ct] = marker_allele_ptr;
}
uint32_t merge_alleles(char** marker_allele_ptrs, uint32_t marker_uidx, uint32_t marker_uidx2) {
  uint32_t distinct_allele_ct = 0;
  char* allele_ptrs[2];
  allele_ptrs[0] = nullptr;
  allele_ptrs[1] = nullptr;
uint32_t merge_equal_pos_alleles(char** marker_allele_ptrs, uint32_t marker_uidx, uint32_t* distinct_allele_ctp, char** allele_ptrs) {
  // reverse order so --keep-allele-order works
  merge_alleles_update_str(marker_allele_ptrs[2 * marker_uidx + 1], allele_ptrs, &distinct_allele_ct);
  merge_alleles_update_str(marker_allele_ptrs[2 * marker_uidx], allele_ptrs, &distinct_allele_ct);
  merge_alleles_update_str(marker_allele_ptrs[2 * marker_uidx2 + 1], allele_ptrs, &distinct_allele_ct);
  merge_alleles_update_str(marker_allele_ptrs[2 * marker_uidx2], allele_ptrs, &distinct_allele_ct);
  if (distinct_allele_ct > 2) {
  merge_alleles_update_str(marker_allele_ptrs[2 * marker_uidx + 1], allele_ptrs, distinct_allele_ctp);
  merge_alleles_update_str(marker_allele_ptrs[2 * marker_uidx], allele_ptrs, distinct_allele_ctp);
  if (*distinct_allele_ctp > 2) {
    return 1;
  }
  if (allele_ptrs[0]) {
    // todo: test if this write is inefficient enough that we want to guard it
    // with an if statement
    marker_allele_ptrs[2 * marker_uidx + 1] = allele_ptrs[0];
    if (allele_ptrs[1]) {
      marker_allele_ptrs[2 * marker_uidx] = allele_ptrs[1];
  return 0;
}
uint32_t save_equal_pos_alleles(const int64_t* ll_buf, uint32_t read_pos, uint32_t read_pos_stop, char** equal_pos_allele_ptrs, char** marker_allele_ptrs) {
  const uint32_t canonical_marker_uidx = (uint32_t)ll_buf[read_pos];
  // (do we really need the reversal in merge_equal_pos_alleles()?)
  // bugfix (26 May 2018): forgot about plink 1.9's allele memory management
  // strategy.
  const char* new_allele = equal_pos_allele_ptrs[1]? equal_pos_allele_ptrs[1] : g_missing_geno_ptr;
  if (allele_reset(new_allele, strlen(new_allele), &(marker_allele_ptrs[canonical_marker_uidx * 2]))) {
    return 1;
  }
  new_allele = equal_pos_allele_ptrs[0]? equal_pos_allele_ptrs[0] : g_missing_geno_ptr;
  if (allele_reset(new_allele, strlen(new_allele), &(marker_allele_ptrs[canonical_marker_uidx * 2 + 1]))) {
    return 1;
  }
  ++read_pos;
  for (; read_pos < read_pos_stop; ++read_pos) {
    const uint32_t cur_marker_uidx = (uint32_t)ll_buf[read_pos];
    // DIRTY HACK (25 May 2018): save (nullptr, canonical_marker_uidx) tuple,
    // and have merge_main() look up the canonical marker_uidx in this case.
    // something like this is necessary for mixed .bed/.ped merge +
    // --merge-equal-pos to work properly.
    // bugfix (26 May 2018): need to free entries here by hand.
    if (marker_allele_ptrs[cur_marker_uidx * 2][1]) {
      free(marker_allele_ptrs[cur_marker_uidx * 2]);
    }
    marker_allele_ptrs[cur_marker_uidx * 2] = nullptr;
    if (marker_allele_ptrs[cur_marker_uidx * 2 + 1][1]) {
      free(marker_allele_ptrs[cur_marker_uidx * 2 + 1]);
    }
    marker_allele_ptrs[cur_marker_uidx * 2 + 1] = (char*)((uintptr_t)canonical_marker_uidx);
  }
  return 0;
}
@@ -15081,6 +15092,10 @@ static inline uint32_t merge_post_msort_update_maps(char* marker_ids, uintptr_t
  uint32_t read_pos = 0;
  uint32_t write_pos = 0; // may be lower than read_pos due to dups
  uint32_t position_warning_ct = 0;
  char* equal_pos_allele_ptrs[2];
  equal_pos_allele_ptrs[0] = nullptr;
  equal_pos_allele_ptrs[1] = nullptr;
  uint32_t equal_pos_allele_ct = 0;
  uint32_t chrom_idx;
  uint32_t chrom_read_end_idx;
  int64_t llxx;
@@ -15096,6 +15111,7 @@ static inline uint32_t merge_post_msort_update_maps(char* marker_ids, uintptr_t
      continue;
    }
    unplaced = (unplaced == 0) || (chrom_info_ptr->zero_extra_chroms && (unplaced > chrom_info_ptr->max_code));
    const uint32_t cur_merge_equal_pos = merge_equal_pos && (!unplaced);
    chrom_read_end_idx = chrom_start[chrom_idx + 1];
    // ll_buf has base-pair positions in high 32 bits, and pre-sort indices in
    // low 32 bits.
@@ -15104,16 +15120,44 @@ static inline uint32_t merge_post_msort_update_maps(char* marker_ids, uintptr_t
    prev_bp = (uint32_t)(((uint64_t)llxx) >> 32);
    pos_buf[write_pos] = prev_bp;
    marker_map[(uint32_t)llxx] = write_pos++;
    uint32_t equal_pos_bp = 0xffffffffU;  // force initial mismatch
    uint32_t equal_pos_read_start = 0;
    for (; read_pos < chrom_read_end_idx; read_pos++) {
      llxx = ll_buf[read_pos];
      presort_idx = (uint32_t)llxx;
      cur_bp = (uint32_t)(llxx >> 32);
      // do not merge chr 0 (unplaced).
      if ((prev_bp == cur_bp) && (!unplaced)) {
	if (merge_equal_pos && merge_alleles(marker_allele_ptrs, ((uint32_t)ll_buf[read_pos - 1]), presort_idx)) {
	  LOGERRPRINTFWW("Error: --merge-equal-pos failure.  Variants '%s' and '%s' have the same position, but do not share the same alleles.\n", &(marker_ids[max_marker_id_len * presort_idx]), &(marker_ids[max_marker_id_len * ((uint32_t)ll_buf[read_pos - 1])]));
      // don't care about position conflicts on chr 0 (unplaced).
      if (cur_merge_equal_pos) {
        // bugfix (25 May 2018): previous merge_alleles() usage was broken for
        // multiple reasons
        if (prev_bp == cur_bp) {
          if (equal_pos_bp != prev_bp) {
            equal_pos_read_start = read_pos - 1;
            equal_pos_bp = prev_bp;
            equal_pos_allele_ptrs[0] = nullptr;
            equal_pos_allele_ptrs[1] = nullptr;
            equal_pos_allele_ct = 0;
            if (merge_equal_pos_alleles(marker_allele_ptrs, (uint32_t)ll_buf[equal_pos_read_start], &equal_pos_allele_ct, equal_pos_allele_ptrs)) {
              LOGERRPRINTFWW("Error: --merge-equal-pos failure: inconsistent alleles at %s:%u.\n", "?", cur_bp);
              return 1;
            }
          }
          if (merge_equal_pos_alleles(marker_allele_ptrs, presort_idx, &equal_pos_allele_ct, equal_pos_allele_ptrs)) {
            LOGERRPRINTFWW("Error: --merge-equal-pos failure: inconsistent alleles at %s:%u.\n", "?", cur_bp);
            return 1;
          }
	  marker_map[presort_idx] = write_pos - 1;
	  continue;
        } else {
          if (equal_pos_bp == prev_bp) {
            if (save_equal_pos_alleles(ll_buf, equal_pos_read_start, read_pos, equal_pos_allele_ptrs, marker_allele_ptrs)) {
              return 1;
            }
          }
          prev_bp = cur_bp;
        }
      } else if ((prev_bp == cur_bp) && (!unplaced)) {
        // shouldn't print warning in --merge-equal-pos case
        LOGPREPRINTFWW("Warning: Variants '%s' and '%s' have the same position.\n", &(marker_ids[max_marker_id_len * presort_idx]), &(marker_ids[max_marker_id_len * ((uint32_t)ll_buf[read_pos - 1])]));
        if (position_warning_ct < 3) {
          logerrprintb();
@@ -15121,10 +15165,6 @@ static inline uint32_t merge_post_msort_update_maps(char* marker_ids, uintptr_t
          logstr(g_logbuf);
        }
        position_warning_ct++;
	if (merge_equal_pos) {
	  marker_map[presort_idx] = write_pos - 1;
	  continue;
	}
      } else {
        prev_bp = cur_bp;
      }
@@ -15132,6 +15172,11 @@ static inline uint32_t merge_post_msort_update_maps(char* marker_ids, uintptr_t
      marker_cms[write_pos] = marker_cms_tmp[presort_idx];
      pos_buf[write_pos++] = cur_bp;
    }
    if (equal_pos_bp == prev_bp) {
      if (save_equal_pos_alleles(ll_buf, equal_pos_read_start, read_pos, equal_pos_allele_ptrs, marker_allele_ptrs)) {
        return 1;
      }
    }
    read_pos = chrom_start[chrom_idx + 1];
    chrom_start[chrom_idx + 1] = write_pos;
  }
@@ -15367,8 +15412,16 @@ int32_t merge_main(char* bedname, char* bimname, char* famname, char* bim_loadbu
      bufptr2[alen1] = '\0';
      alen2 = strlen_se(bufptr3);
      bufptr3[alen2] = '\0';
      bufptr4 = marker_allele_ptrs[((uint32_t)ii) * 2];
      bufptr5 = marker_allele_ptrs[((uint32_t)ii) * 2 + 1];
      uint32_t canonical_ascii_uidx = (uint32_t)ii;
      bufptr4 = marker_allele_ptrs[canonical_ascii_uidx * 2];
      bufptr5 = marker_allele_ptrs[canonical_ascii_uidx * 2 + 1];
      if (!bufptr4) {
        // --merge-equal-pos non-canonical index.  Retrieve the canonical
        // index.
        canonical_ascii_uidx = (uintptr_t)bufptr5;
        bufptr4 = marker_allele_ptrs[canonical_ascii_uidx * 2];
        bufptr5 = marker_allele_ptrs[canonical_ascii_uidx * 2 + 1];
      }
      last_marker_in_idx = marker_in_idx;
      if (!cur_sample_ct) {
@@ -15531,7 +15584,7 @@ int32_t merge_main(char* bedname, char* bimname, char* famname, char* bim_loadbu
		if (!umm) {
		  diff_discordant++;
		}
		if (merge_diff_print(outfile, idbuf, bufptr, &(sample_ids[ujj * max_sample_id_len]), ucc, ucc3, &(marker_allele_ptrs[((uint32_t)ii) * 2]))) {
		if (merge_diff_print(outfile, idbuf, bufptr, &(sample_ids[ujj * max_sample_id_len]), ucc, ucc3, &(marker_allele_ptrs[canonical_ascii_uidx * 2]))) {
		  goto merge_main_ret_WRITE_FAIL;
		}
	      }
@@ -15669,6 +15722,15 @@ int32_t merge_main(char* bedname, char* bimname, char* famname, char* bim_loadbu
	}
	// actual relative position
	marker_out_idx = marker_map[uii] - start_marker_idx;
        // bugfix (25 May 2018): in --merge-equal-pos case, we need to update a
        // single canonical marker_allele_ptrs[].  We now handle this by
        // storing nullptr in [0] and the canonical index in [1] when the
        // current index is non-canonical.
        char** canonical_marker_allele_ptrs = &(marker_allele_ptrs[uii * 2]);
        if (!canonical_marker_allele_ptrs[0]) {
          const uint32_t canonical_ascii_uidx = (uintptr_t)canonical_marker_allele_ptrs[1];
          canonical_marker_allele_ptrs = &(marker_allele_ptrs[canonical_ascii_uidx * 2]);
        }
	if ((*aptr1 == '0') && (alen1 == 1)) {
          if ((*aptr2 != '0') || (alen2 != 1)) {
@@ -15679,39 +15741,39 @@ int32_t merge_main(char* bedname, char* bimname, char* famname, char* bim_loadbu
	  goto merge_main_ret_HALF_MISSING;
	} else {
	  ucc2 = 0; // A2 count
	  if (!strcmp(aptr1, marker_allele_ptrs[uii * 2 + 1])) {
	  if (!strcmp(aptr1, canonical_marker_allele_ptrs[1])) {
	    ucc2++;
	  } else if (strcmp(aptr1, marker_allele_ptrs[uii * 2])) {
	  } else if (strcmp(aptr1, canonical_marker_allele_ptrs[0])) {
	    // new allele code
	    if (marker_allele_ptrs[uii * 2 + 1] == missing_geno_ptr) {
	    if (canonical_marker_allele_ptrs[1] == missing_geno_ptr) {
	      // fill A2 first
	      ucc2++;
	      ukk = uii * 2 + 1;
	    } else if (marker_allele_ptrs[uii * 2] == missing_geno_ptr) {
	      ukk = uii * 2;
	      ukk = 1;
	    } else if (canonical_marker_allele_ptrs[0] == missing_geno_ptr) {
	      ukk = 0;
	    } else {
	      goto merge_main_ret_NOT_BIALLELIC;
	    }
	    if (allele_set(aptr1, alen1, &(marker_allele_ptrs[ukk]))) {
	    if (allele_set(aptr1, alen1, &(canonical_marker_allele_ptrs[ukk]))) {
	      goto merge_main_ret_NOMEM;
	    }
	  }
	  if (!strcmp(aptr2, marker_allele_ptrs[uii * 2 + 1])) {
	  if (!strcmp(aptr2, canonical_marker_allele_ptrs[1])) {
	    ucc2++;
	  } else if (strcmp(aptr2, marker_allele_ptrs[uii * 2])) {
	  } else if (strcmp(aptr2, canonical_marker_allele_ptrs[0])) {
	    // put A2 check second since the only way A2 will be unset when A1
	    // is set at this point is if it was specified that way in an
	    // earlier binary file.
	    if (marker_allele_ptrs[uii * 2] == missing_geno_ptr) {
	      ukk = uii * 2;
	    } else if (marker_allele_ptrs[uii * 2 + 1] == missing_geno_ptr) {
              ukk = uii * 2 + 1;
	    if (canonical_marker_allele_ptrs[0] == missing_geno_ptr) {
	      ukk = 0;
	    } else if (canonical_marker_allele_ptrs[1] == missing_geno_ptr) {
              ukk = 1;
              // bugfix (14 Nov 2017): forgot to increment the A2 allele count!
              ++ucc2;
	    } else {
	      goto merge_main_ret_NOT_BIALLELIC;
	    }
	    if (allele_set(aptr2, alen2, &(marker_allele_ptrs[ukk]))) {
	    if (allele_set(aptr2, alen2, &(canonical_marker_allele_ptrs[ukk]))) {
	      goto merge_main_ret_NOMEM;
	    }
	  }
@@ -15772,7 +15834,7 @@ int32_t merge_main(char* bedname, char* bimname, char* famname, char* bim_loadbu
	      if (!umm) {
		diff_discordant++;
	      }
	      if (merge_diff_print(outfile, idbuf, &(marker_ids[uii * max_marker_id_len]), &(sample_ids[((uint32_t)ii) * max_sample_id_len]), ucc2, ucc3, &(marker_allele_ptrs[uii * 2]))) {
	      if (merge_diff_print(outfile, idbuf, &(marker_ids[uii * max_marker_id_len]), &(sample_ids[((uint32_t)ii) * max_sample_id_len]), ucc2, ucc3, canonical_marker_allele_ptrs)) {
		goto merge_main_ret_WRITE_FAIL;
	      }
	    }
@@ -15786,7 +15848,7 @@ int32_t merge_main(char* bedname, char* bimname, char* famname, char* bim_loadbu
	      diff_not_both_genotyped++;
	    } else if (ucc2 != ucc3) {
	      diff_discordant++;
	      if (merge_diff_print(outfile, idbuf, &(marker_ids[uii * max_marker_id_len]), &(sample_ids[((uint32_t)ii) * max_sample_id_len]), ucc2, ucc3, &(marker_allele_ptrs[uii * 2]))) {
	      if (merge_diff_print(outfile, idbuf, &(marker_ids[uii * max_marker_id_len]), &(sample_ids[((uint32_t)ii) * max_sample_id_len]), ucc2, ucc3, canonical_marker_allele_ptrs)) {
		goto merge_main_ret_WRITE_FAIL;
	      }
	    }
@@ -16648,7 +16710,11 @@ int32_t merge_datasets(char* bedname, char* bimname, char* famname, char* outnam
    break;
  }
 merge_datasets_ret_1:
  if (merge_equal_pos) {
    cleanup_allele_storage2(tot_marker_ct * 2, marker_allele_ptrs);
  } else {
    cleanup_allele_storage(2, tot_marker_ct * 2, marker_allele_ptrs);
  }
  fclose_cond(mergelistfile);
  fclose_cond(outfile);
  bigstack_double_reset(bigstack_mark, bigstack_end_mark);