static char rcsid[] = "$Id: d11d5b2ef10a5f7675a34c0f312ed570daa82dd2 $";
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "splice.h"

#include <stdio.h>
#include <string.h>

#include "mem.h"
#include "assert.h"
#include "sense.h"

#include "genomebits_count.h"
#include "genomebits_mismatches.h"
#include "spliceends.h"

#include "genome.h"
#include "genome_sites.h"
#include "maxent.h"
#include "maxent_hr.h"
#include "univcoord.h"
#include "complement.h"


/* Causes problems with counting mismatches */
/* #define TRIM_AT_CHROMOSOME_BOUNDS 1 */


#define LOWPROB_SUPPORT 20
#define MIN_SUPPORT_SPLICE 6	/* First level in sufficient_support_p */
#define MIN_SUPPORT_SPLICE_PLUS_INDEL 12

#define MIN_PROB 0.85		/* For non-salvage */
#define PROB_SLOP 0.2
#define MISMATCHES_SLOP 1

/* #define MIN_SPLICE_PROB 0.4 */	/* Skip if both probs are less than this */
#define MIN_SPLICE_PLUS_INDEL_PROB 0.5 /* Skip if either prob is less than this */


#if 0
/* Creates issues with ambiguous substrings */
#define LOCALSPLICING_NMATCHES_SLOP 1
#else
#define LOCALSPLICING_NMATCHES_SLOP 0
#endif
#define LOCALSPLICING_PROB_SLOP 0.05

#define SLOP 1


/* Splice_resolve */
#ifdef DEBUG1
#define debug1(x) x
#else
#define debug1(x)
#endif

/* Splice_resolve_fusion */
#ifdef DEBUG2
#define debug2(x) x
#else
#define debug2(x)
#endif

/* Splice_resolve_fusion, counting mismatches */
#ifdef DEBUG2A
#define debug2a(x) x
#else
#define debug2a(x)
#endif

/* sufficient_support_p */
#ifdef DEBUG3
#define debug3(x) x
#else
#define debug3(x)
#endif

/* known splicing */
#ifdef DEBUG4S
#define debug4s(x) x
#else
#define debug4s(x)
#endif


static bool novelsplicingp;

static Genomebits_T genomebits;
static Genomebits_T genomebits_alt;

static int min_shortend;

static char complCode[128] = COMPLEMENT_LC;


#ifdef DEBUG2
static void
make_complement_inplace (char *sequence, unsigned int length) {
  char temp;
  unsigned int i, j;

  for (i = 0, j = length-1; i < length/2; i++, j--) {
    temp = complCode[(int) sequence[i]];
    sequence[i] = complCode[(int) sequence[j]];
    sequence[j] = temp;
  }
  if (i == j) {
    sequence[i] = complCode[(int) sequence[i]];
  }

  return;
}
#endif


void
Splice_setup (Genomebits_T genomebits_in, Genomebits_T genomebits_alt_in,
	      bool novelsplicingp_in, int min_shortend_in) {

  genomebits = genomebits_in;
  genomebits_alt = genomebits_alt_in;
  novelsplicingp = novelsplicingp_in;
  min_shortend = min_shortend_in;
  /* max_end_length = 2*(index1part_in + index1interval_in - 1); */

  return;
}


void
Spliceinfo_free (Spliceinfo_T *old) {
  FREE((*old)->segmentj_partners);
  FREE((*old)->segmenti_partners);

  FREE((*old)->segmentj_knowni);
  FREE((*old)->segmenti_knowni);
  FREE((*old)->segmentj_knownpos);
  FREE((*old)->segmenti_knownpos);
  FREE((*old)->segmentj_knowni_alloc);
  FREE((*old)->segmenti_knowni_alloc);

  FREE((*old)->segmentj_qpos_alloc);
  FREE((*old)->segmenti_qpos_alloc);

  FREE((*old)->mismatch_positions_left);
  FREE((*old)->mismatch_positions_right);

  FREE(*old);

  return;
}


/* The only information accessed externally is ambig_qstarts and ambig_qends */
Spliceinfo_T
Spliceinfo_new (int querylength) {
  Spliceinfo_T new = (Spliceinfo_T) MALLOC(sizeof(*new));

  /* MISMATCH_EXTRA defined in genomebits_mismatches.h */
  new->mismatch_positions_left = (int *) MALLOC((querylength + MISMATCH_EXTRA)*sizeof(int));
  new->mismatch_positions_right = (int *) MALLOC((querylength + MISMATCH_EXTRA)*sizeof(int));

  new->segmenti_qpos_alloc = (int *) MALLOC((querylength + 1)*sizeof(int));
  new->segmentj_qpos_alloc = (int *) MALLOC((querylength + 1)*sizeof(int));

  new->segmenti_knowni_alloc = (int *) MALLOC((querylength + 1)*sizeof(int));
  new->segmentj_knowni_alloc = (int *) MALLOC((querylength + 1)*sizeof(int));
  new->segmenti_knownpos = (int *) MALLOC((querylength + 1)*sizeof(int));
  new->segmentj_knownpos = (int *) MALLOC((querylength + 1)*sizeof(int));
  new->segmenti_knowni = (int *) MALLOC((querylength + 1)*sizeof(int));
  new->segmentj_knowni = (int *) MALLOC((querylength + 1)*sizeof(int));

  new->segmenti_partners = (Univcoord_T *) MALLOC((querylength + 1)*sizeof(Univcoord_T));
  new->segmentj_partners = (Univcoord_T *) MALLOC((querylength + 1)*sizeof(Univcoord_T));

  return new;
}

/* Note: contents of spliceinfo are filled in by kmer-search and path-solve procedures */


/* Same as in spliceindel.c */
static bool
sufficient_support_p (int adj_support, double splice_prob) {
  debug1(printf("Checking for sufficient splice prob, based on adj_support %d and splice prob %.2f\n",
		adj_support,splice_prob));

  if (splice_prob > 0.95) {
    return (adj_support >= 6) ? true : false; /* threshold set to MIN_SUPPORT_SPLICE */

  } else if (splice_prob > 0.90) {
    return (adj_support >= 8) ? true : false;

  } else if (splice_prob > 0.80) {
    return (adj_support >= 12) ? true : false;

  } else if (splice_prob > 0.50) {
    return (adj_support >= 15) ? true : false;

  } else {
    return (adj_support >= 20) ? true : false;
  }
}


#if 0
/* Do not compare against true or false */
/* Want loose criterion, otherwise, we incur slowdown from having to
   run GSNAP algorithm */
static int
sufficient_splice_prob_local (int support, int nmismatches, double spliceprob) {
  support -= 3*nmismatches;
  if (support <= 9) {
    return (spliceprob > 0.80);
  } else if (support <= 12) {
    return (spliceprob > 0.70);
  } else if (support <= 15) {
    return (spliceprob > 0.60);
  } else if (support <= 25) {
    return (spliceprob > 0.50);
  } else {
    return (spliceprob > 0.40);
  }
}
#endif


/* Re-uses mismatch_positions_left and mismatch_positions_right computed by caller */
static int
find_middle_exon (Univcoord_T *best_middle_univdiagonal, int *best_splice_qpos_i, int *best_splice_qpos_j,
		  int *best_nmismatches_i, int *best_nmismatches_middle, int *best_nmismatches_j,
		  int *best_ref_nmismatches_i, int *best_ref_nmismatches_middle, int *best_ref_nmismatches_j,
		  double *best_donor_prob, double *best_acceptor_prob,

		  Univcoord_T univdiagonal_i, Univcoord_T univdiagonal_j,
		  int pos5, int pos3, int splice_qpos_5, int splice_qpos_3, int querylength,

		  int *mismatch_positions_left, int *mismatch_positions_right,
		  Compress_T query_compress, int nmismatches_left, int nmismatches_right,
		  Spliceinfo_T spliceinfo, Knownsplicing_T knownsplicing,
		  bool plusp, bool sense_forward_p, int genestrand) {
  int splice_qpos_i, splice_qpos_j;
  int best_nmismatches, nmismatches, nmismatches_middle, ref_nmismatches_middle, lefti, righti;

  int segmenti_nsites, segmentj_nsites, i, j;
  int *segmenti_positions, *segmentj_positions;
  Univcoord_T *endpoints, *segmenti_partners, *segmentj_partners;
  uint64_t low_rank, high_rank, rank;
  
  Univcoord_T middle_univdiagonal, middle_left;
  Univcoord_T segmenti_left, segmentj_left;
  

  debug1(printf("Entering find_middle_exon with pos5 %d, splice_qpos_5 %d, splice_qpos_3 %d, pos3 %d\n",
		pos5,splice_qpos_5,splice_qpos_3,pos3));

  debug1(
	 printf("(1) %d mismatches on left from %d to %d at:",nmismatches_left,pos5,pos3);
	 for (i = 0; i <= nmismatches_left; i++) {
	   printf(" %d",mismatch_positions_left[i]);
	 }
	 printf("\n");
	 );

  debug1(
	 printf("(1) %d mismatches on right from %d to %d at:",nmismatches_right,pos3,pos5);
	 for (i = 0; i <= nmismatches_right; i++) {
	   printf(" %d",mismatch_positions_right[i]);
	 }
	 printf("\n");
	 );

  segmenti_left = univdiagonal_i - querylength;
  segmentj_left = univdiagonal_j - querylength;

  if (plusp == sense_forward_p) {
    /* plus sense or minus antisense */
    segmenti_nsites = 0;
    segmenti_positions = spliceinfo->segmenti_qpos_alloc;
    segmenti_partners = spliceinfo->segmenti_partners; /* Use allocated memory */

    endpoints = Knownsplicing_donors(&low_rank,&high_rank,knownsplicing,
				     univdiagonal_i,querylength,pos5,splice_qpos_5);
    debug1(printf("Knownsplicing donors at %u+%d..%d yields low_rank %lu to high_rank %lu\n",
		  segmenti_left,pos5,splice_qpos_5,low_rank,high_rank));
    /* Don't collapse duplicate endpoints, because we care about the partners */
    if ((int) (high_rank - low_rank) > querylength) {
      /* Skip, since we don't have any more space allocated */
    } else {
      for (rank = low_rank; rank < high_rank; rank++) {
	debug4s(printf("Setting known donor %d for segmenti at %u..%u\n",(int) rank,endpoints[2*rank],endpoints[2*rank+1]));
	segmenti_positions[segmenti_nsites] = endpoints[2*rank] - segmenti_left;
	segmenti_partners[segmenti_nsites++] = endpoints[2*rank+1];
      }
    }

#ifdef DEBUG1
    printf("Found %d known donori sites:",segmenti_nsites);
    for (i = 0; i < segmenti_nsites; i++) {
      printf(" %d (%u)",segmenti_positions[i],segmenti_partners[i]);
    }
    printf("\n");
#endif

    segmentj_nsites = 0;
    segmentj_positions = spliceinfo->segmentj_qpos_alloc;
    segmentj_partners = spliceinfo->segmentj_partners; /* Use allocated memory */

    endpoints = Knownsplicing_acceptors(&low_rank,&high_rank,knownsplicing,
					univdiagonal_j,querylength,splice_qpos_3,pos3);
    debug1(printf("Knownsplicing acceptors at %u+%d..%d yields low_rank %lu to high_rank %lu\n",
		  segmentj_left,splice_qpos_3,pos3,low_rank,high_rank));
    /* Don't collapse duplicate endpoints, because we care about the partners */
    if ((int) (high_rank - low_rank) > querylength) {
      /* Skip, since we don't have any more space allocated */
    } else {
      for (rank = low_rank; rank < high_rank; rank++) {
	debug4s(printf("Setting known acceptor %d for segmentj at %u..%u\n",(int) rank,endpoints[2*rank],endpoints[2*rank+1]));
	segmentj_positions[segmentj_nsites] = endpoints[2*rank] - segmentj_left;
	segmentj_partners[segmentj_nsites++] = endpoints[2*rank+1];
      }
    }
#ifdef DEBUG1
    printf("Found %d known acceptorj sites:",segmentj_nsites);
    for (i = 0; i < segmentj_nsites; i++) {
      printf(" %d (%u)",segmentj_positions[i],segmentj_partners[i]);
    }
    printf("\n");
#endif

  } else {
    /* minus sense or plus antisense */
    segmenti_nsites = 0;
    segmenti_positions = spliceinfo->segmenti_qpos_alloc;
    segmenti_partners = spliceinfo->segmenti_partners; /* Use allocated memory */
    
    endpoints = Knownsplicing_antiacceptors(&low_rank,&high_rank,knownsplicing,
					    univdiagonal_i,querylength,pos5,splice_qpos_5);
    debug1(printf("Knownsplicing antiacceptors at %u+%d..%d yields low_rank %lu to high_rank %lu\n",
		  segmenti_left,pos5,splice_qpos_5,low_rank,high_rank));
    /* Don't collapse duplicate endpoints, because we care about the partners */
    if ((int) (high_rank - low_rank) > querylength) {
      /* Skip, since we don't have any more space allocated */
    } else {
      for (rank = low_rank; rank < high_rank; rank++) {
	debug4s(printf("Setting known antiacceptor %d for segmenti at %u..%u\n",(int) rank,endpoints[2*rank],endpoints[2*rank+1]));
	segmenti_positions[segmenti_nsites] = endpoints[2*rank] - segmenti_left;
	segmenti_partners[segmenti_nsites++] = endpoints[2*rank+1];
      }
    }
#ifdef DEBUG1
    printf("Found %d known antiacceptori sites:",segmenti_nsites);
    for (i = 0; i < segmenti_nsites; i++) {
      printf(" %d (%u)",segmenti_positions[i],segmenti_partners[i]);
      printf("\n");
    }
#endif

    segmentj_nsites = 0;
    segmentj_positions = spliceinfo->segmentj_qpos_alloc;
    segmentj_partners = spliceinfo->segmentj_partners; /* Use allocated memory */

    endpoints = Knownsplicing_antidonors(&low_rank,&high_rank,knownsplicing,
					 univdiagonal_j,querylength,splice_qpos_3,pos3);
    debug1(printf("Knownsplicing antidonors at %u+%d..%d yields low_rank %lu to high_rank %lu\n",
		  segmentj_left,splice_qpos_3,pos3,low_rank,high_rank));
    /* Don't collapse duplicate endpoints, because we care about the partners */
    if ((int) (high_rank - low_rank) > querylength) {
      /* Skip, since we don't have any more space allocated */
    } else {
      for (rank = low_rank; rank < high_rank; rank++) {
	debug4s(printf("Setting known antidonor %d for segmentj at %u..%u\n",(int) rank,endpoints[2*rank],endpoints[2*rank+1]));
	segmentj_positions[segmentj_nsites] = endpoints[2*rank] - segmentj_left;
	segmentj_partners[segmentj_nsites++] = endpoints[2*rank+1];
      }
    }
#ifdef DEBUG1
    printf("Found %d known antidonorj sites:",segmentj_nsites);
    for (i = 0; i < segmentj_nsites; i++) {
      printf(" %d (%u)",segmentj_positions[i],segmentj_partners[i]);
    }
    printf("\n");
#endif
  }

  /* Caller has set *best_middle_univdiagonal to be 0 */
  *best_splice_qpos_i = *best_splice_qpos_j = -1;
  best_nmismatches = querylength;
  for (i = 0; i < segmenti_nsites; i++) {
    splice_qpos_i = segmenti_positions[i];
    for (j = 0; j < segmentj_nsites; j++) {
      splice_qpos_j = segmentj_positions[j];
      if (splice_qpos_j - splice_qpos_i == (int) (segmentj_partners[j] - segmenti_partners[i])) {
	middle_left = segmenti_partners[i] - splice_qpos_i;

	middle_univdiagonal = middle_left + querylength;
	nmismatches_middle =
	  Genomebits_count_mismatches_substring(&ref_nmismatches_middle,genomebits,genomebits_alt,
						query_compress,/*univdiagonal*/middle_univdiagonal,querylength,
						/*pos5*/splice_qpos_i,/*pos3*/splice_qpos_j,
						plusp,genestrand);

	debug1(printf("Counting mismatches on segmenti up to %d:\n",splice_qpos_i));
	lefti = 0;
	while (lefti < nmismatches_left && mismatch_positions_left[lefti] < splice_qpos_i) {
	  debug1(printf("Saw segmenti mismatch at %d\n",mismatch_positions_left[lefti]));
	  lefti++;
	}

	debug1(printf("Counting mismatches on segmentj down to %d:\n",splice_qpos_j));
	righti = 0;
	while (righti < nmismatches_right && mismatch_positions_right[righti] >= splice_qpos_j) {
	  debug1(printf("Saw segmentj mismatch at %d\n",mismatch_positions_right[righti]));
	  righti++;
	}

	debug1(printf("For splices %d and %d, total_nmismatches: %d + %d + %d\n",
		      splice_qpos_i,splice_qpos_j,lefti,nmismatches_middle,righti));
	if ((nmismatches = lefti + nmismatches_middle + righti) < best_nmismatches) {
	  *best_middle_univdiagonal = middle_univdiagonal;
	  *best_splice_qpos_i = splice_qpos_i;
	  *best_splice_qpos_j = splice_qpos_j;
	  *best_nmismatches_i = *best_ref_nmismatches_i = lefti;
	  *best_nmismatches_middle = nmismatches_middle;
	  *best_ref_nmismatches_middle = ref_nmismatches_middle;
	  *best_nmismatches_j = *best_ref_nmismatches_j = righti;
	  *best_donor_prob = *best_acceptor_prob = 1.0; /* Because of knownsplicing */
	  best_nmismatches = nmismatches;
	}
      }
    }
  }

  debug1(printf("Best candidate middle exon is %d..%d for univdiagonal %u with %d segmenti, %d middle, and %d segmentj mismatches\n",
		*best_splice_qpos_i,*best_splice_qpos_j,*best_middle_univdiagonal,*best_nmismatches_i,*best_nmismatches_middle,*best_nmismatches_j));

  return -1;
}



static int
spliceindel_resolve (int *best_nindels, int *best_indel_pos,
		     int *best_nmismatches_i, int *best_nmismatches_j, int *best_nmismatches_indel,
		     int *best_ref_nmismatches_i, int *best_ref_nmismatches_j,
		     int *best_ref_nmismatches_indel, double *best_donor_prob, double *best_acceptor_prob,
		     
		     Univcoord_T univdiagonal_i, Univcoord_T univdiagonal_j,
		     Compress_T query_compress, bool plusp, Univcoord_T chroffset, Univcoord_T chrhigh,

		     int *mismatch_positions_left, int nmismatches_left,
		     int *mismatch_positions_right, int nmismatches_right,

		     int segmenti_nsites, int segmentj_nsites,
		     int *segmenti_positions, int *segmentj_positions,
		     int *segmenti_knowni, int *segmentj_knowni,
		     
		     int pos5, int pos3, int querylength,
		     Indelinfo_T indelinfo, bool sense_forward_p, int genestrand,
		     int nmismatches_allowed, int max_insertionlen, int max_deletionlen) {

  int best_splice_qpos, splice_qpos, i, j;

  int best_nmismatches, nmismatches, nmismatches1, nmismatches2, ref_nmismatches1, ref_nmismatches2;

  int nindels, indel_pos;
  int nmismatches_indel, nmismatches_i, nmismatches_j;
  double best_prob, prob, best_probi, best_probj, probi, probj;
  Univcoord_T segmenti_left, segmentj_left;

  segmenti_left = univdiagonal_i - querylength;
  segmentj_left = univdiagonal_j - querylength;


  best_splice_qpos = -1;
  best_prob = 0.0;
  best_nmismatches = nmismatches_allowed + 1;

  debug1(printf("Comparing max_deletionlen %d with %d\n",max_deletionlen,(int) (univdiagonal_j - univdiagonal_i)));
  if (max_deletionlen > (int) (univdiagonal_j - univdiagonal_i)) {
    /* The sum of the deletion length and splice distance must be less than the distance in the genome */
    max_deletionlen = (int) (univdiagonal_j - univdiagonal_i);
  }

  /* Left anchor (splice) */
  /* Advancing segmenti splice site from low qpos to high qpos.  Same direction for segmentj */
  /* All splicesites run from low qpos to high qpos */
  debug1(printf(">Left anchor -- splice on segmenti and indel on segmentj:\n"));
  nmismatches_i = 0;
  i = 0;
  j = 0;

  /* Count mismatches, which are also from low qpos to high qpos */
  splice_qpos = segmenti_positions[i];
  while (nmismatches_i <= nmismatches_left && mismatch_positions_left[nmismatches_i] < splice_qpos) {
    nmismatches_i++;
  }
#ifdef DEBUG1
  if (nmismatches_i > nmismatches_allowed) {
    printf("(1) nmismatches_i for splice_qpos %d is >= %d (exceeds nmismatches_allowed)\n",
	   splice_qpos,nmismatches_i);
  } else {
    printf("(1) nmismatches_i for splice_qpos %d is %d\n",splice_qpos,nmismatches_i);
  }
#endif
  
  while (i < segmenti_nsites && nmismatches_i <= nmismatches_allowed) {
    if (segmenti_knowni[i] >= 0) {
      probi = 1.0;
    } else if (plusp == sense_forward_p) {
      probi = Maxent_hr_donor_prob(segmenti_left + splice_qpos,chroffset);
    } else {
      probi = Maxent_hr_antiacceptor_prob(segmenti_left + splice_qpos,chroffset);
    }
    debug1(printf("Probi at %d is %f\n",splice_qpos,probi));

    if (probi > SPLICE_PROB_LOW) {
      /* Backup to low qpos, and then advance forward */
      while (j - 1 >= 0 && splice_qpos - segmentj_positions[j-1] <= max_deletionlen) {
	debug1(printf("Backing up j to %d because splice_qpos %d - %d < max_deletionlen %d\n",
		      j - 1,splice_qpos,segmentj_positions[j-1],max_deletionlen));
	j--;
      }

      /* Advance */
      while (j < segmentj_nsites && splice_qpos - segmentj_positions[j] > max_deletionlen) {
	j++;
      }

      /* Deletions on segmentj */
      while (j < segmentj_nsites && segmentj_positions[j] < splice_qpos) {
	assert(splice_qpos - segmentj_positions[j] <= max_deletionlen);
	if (segmentj_knowni[j] >= 0) {
	  probj = 1.0;
	} else if (plusp == sense_forward_p) {
	  probj = Maxent_hr_acceptor_prob(segmentj_left + segmentj_positions[j],chroffset);
	} else {
	  probj = Maxent_hr_antidonor_prob(segmentj_left + segmentj_positions[j],chroffset);
	}
	debug1(printf("Deletion: probj at %d is %f\n",segmentj_positions[j],probj));

	if (probj > SPLICE_PROB_HIGH || (probj > SPLICE_PROB_LOW && probi > SPLICE_PROB_HIGH)) {
	  nindels = segmentj_positions[j] - splice_qpos; /* Should be negative */
	  debug1(printf("segmenti_left %u, segmentj_left %u, nindels %d\n",
			segmenti_left - chroffset,segmentj_left - chroffset,nindels));
	  debug1(printf("Trying deletion on segmentj of %d from %d to %d",nindels,splice_qpos,segmentj_positions[j]));
	  /* Can re-use mismatch_positions_right because it is based on (segmentj_left + nindels) - nindels */
	  if ((indel_pos = Indel_resolve_middle_deletion(&nmismatches1,&nmismatches2,&ref_nmismatches1,&ref_nmismatches2,
							 univdiagonal_j + nindels,nindels,chrhigh,
							 /*mismatch_positions_left*/NULL,/*nmismatches_left*/0,
							 /*re-use*/mismatch_positions_right,/*re-use*/nmismatches_right,
							 /*ome*/genomebits,/*ome_alt*/genomebits_alt,
							 query_compress,/*pos5*/splice_qpos,pos3,
							 querylength,indelinfo,plusp,genestrand,
							 /*want_lowest_coordinate_p*/true)) < 0) {
	    debug1(printf(" => could not find deletion on segmentj\n"));
	  } else {
	    assert(indel_pos > splice_qpos);
	    assert(indel_pos < pos3);
	    /* support_indel = indel_pos - splice_qpos; */
	    nmismatches_indel = nmismatches1;	  /* From splice to indel */
	    nmismatches_j = nmismatches2;
	    debug1(printf(" => splice_qpos %d, indel_pos %d, nmismatches_i %d, mismatches_indel %d, mismatches_j %d, prob %f",
			  splice_qpos,indel_pos,nmismatches_i,nmismatches_indel,nmismatches_j,probi+probj));
	    if ((prob = probi + probj) > best_prob) {
	      debug1(printf(" **"));
	      *best_nindels = -nindels; /* Flip sign */
	      *best_indel_pos = indel_pos;
	      *best_nmismatches_i = *best_ref_nmismatches_i = nmismatches_i;
	      *best_nmismatches_indel = *best_ref_nmismatches_indel = nmismatches_indel;
	      *best_nmismatches_j = *best_ref_nmismatches_j = nmismatches_j;
	      best_splice_qpos = splice_qpos;
	      /* best_knowni_i = segmenti_knowni[i]; */
	      /* best_knowni_j = segmentj_knowni[j]; */
	      best_probi = probi;
	      best_probj = probj;
	      best_prob = prob;
	      best_nmismatches = nmismatches_indel + nmismatches_i + nmismatches_j;
	    } else if (prob > best_prob - PROB_SLOP &&
		       (nmismatches = nmismatches_indel + nmismatches_i + nmismatches_j) < best_nmismatches) {
	      debug1(printf(" **"));
	      *best_nindels = -nindels; /* Flip sign */
	      *best_indel_pos = indel_pos;
	      *best_nmismatches_i = *best_ref_nmismatches_i = nmismatches_i;
	      *best_nmismatches_indel = *best_ref_nmismatches_indel = nmismatches_indel;
	      *best_nmismatches_j = *best_ref_nmismatches_j = nmismatches_j;
	      best_splice_qpos = splice_qpos;
	      /* best_knowni_i = segmenti_knowni[i]; */
	      /* best_knowni_j = segmentj_knowni[j]; */
	      best_probi = probi;
	      best_probj = probj;
	      best_prob = prob;
	      best_nmismatches = nmismatches;
	    }
	    debug1(printf("\n"));
	  }
	}
	
	j++;
      }

      if (j < segmentj_nsites && segmentj_positions[j] == splice_qpos) {
	/* Splice without indel */
	j++;
      }

      /* Insertions on segmentj */
      while (j < segmentj_nsites && segmentj_positions[j] - splice_qpos <= max_insertionlen) {
	if (segmentj_knowni[j] >= 0) {
	  probj = 1.0;
	} else if (plusp == sense_forward_p) {
	  probj = Maxent_hr_acceptor_prob(segmentj_left + segmentj_positions[j],chroffset);
	} else {
	  probj = Maxent_hr_antidonor_prob(segmentj_left + segmentj_positions[j],chroffset);
	}
	debug1(printf("Insertion: probj at %d is %f\n",segmentj_positions[j],probj));
	if (probj > SPLICE_PROB_HIGH || (probj > SPLICE_PROB_LOW && probi > SPLICE_PROB_HIGH)) {
	  nindels = segmentj_positions[j] - splice_qpos; /* Should be positive */
	  debug1(printf("segmenti_left %u, segmentj_left %u, nindels %d\n",
			segmenti_left - chroffset,segmentj_left - chroffset,nindels));
	  debug1(printf("Trying insertion on segmentj of %d from %d to %d",nindels,splice_qpos,segmentj_positions[j]));
	  /* Can re-use mismatch_positions_right because it is based on (segmentj_left + nindels) - nindels */
	  if ((indel_pos = Indel_resolve_middle_insertion(&nmismatches1,&nmismatches2,&ref_nmismatches1,&ref_nmismatches2,
							  univdiagonal_j + nindels,nindels,chrhigh,
							  /*mismatch_positions_left*/NULL,/*nmismatches_left*/0,
							  /*re-use*/mismatch_positions_right,/*re-use*/nmismatches_right,
							  /*ome*/genomebits,/*ome_alt*/genomebits_alt,
							  query_compress,/*pos5*/splice_qpos,pos3,
							  querylength,indelinfo,plusp,genestrand,
							  /*want_lowest_coordinate_p*/true)) < 0) {
	    debug1(printf(" => Could not find insertion on segmentj\n"));
	  } else {
	    assert(indel_pos > splice_qpos);
	    assert(indel_pos + nindels < pos3);
	    /* support_indel = indel_pos - splice_qpos; */
	    nmismatches_indel = nmismatches1;	  /* From splice to indel */
	    nmismatches_j = nmismatches2;
	    debug1(printf(" => splice_qpos %d, indel_pos %d, mismatches_i %d, mismatches_indel %d, mismatches_j %d, prob %f",
			  splice_qpos,indel_pos,nmismatches_i,nmismatches_indel,nmismatches_j,probi+probj));
	    if ((prob = probi + probj) > best_prob) {
	      debug1(printf(" **"));
	      *best_nindels = -nindels; /* Flip sign */
	      *best_indel_pos = indel_pos;
	      *best_nmismatches_i = *best_ref_nmismatches_i = nmismatches_i;
	      *best_nmismatches_indel = *best_ref_nmismatches_indel = nmismatches_indel;
	      *best_nmismatches_j = *best_ref_nmismatches_j = nmismatches_j;
	      best_splice_qpos = splice_qpos;
	      /* best_knowni_i = segmenti_knowni[i]; */
	      /* best_knowni_j = segmentj_knowni[j]; */
	      best_probi = probi;
	      best_probj = probj;
	      best_prob = prob;
	      best_nmismatches = nmismatches_indel + nmismatches_i + nmismatches_j;
	    } else if (prob > best_prob - PROB_SLOP &&
		       (nmismatches = nmismatches_indel + nmismatches_i + nmismatches_j) < best_nmismatches) {		
	      debug1(printf(" **"));
	      *best_nindels = -nindels; /* Flip sign */
	      *best_indel_pos = indel_pos;
	      *best_nmismatches_i = *best_ref_nmismatches_i = nmismatches_i;
	      *best_nmismatches_indel = *best_ref_nmismatches_indel = nmismatches_indel;
	      *best_nmismatches_j = *best_ref_nmismatches_j = nmismatches_j;
	      best_splice_qpos = splice_qpos;
	      /* best_knowni_i = segmenti_knowni[i]; */
	      /* best_knowni_j = segmentj_knowni[j]; */
	      best_probi = probi;
	      best_probj = probj;
	      best_prob = prob;
	      best_nmismatches = nmismatches;
	    }
	    debug1(printf("\n"));
	  }
	}

	j++;
      }
    }

    if (++i < segmenti_nsites) {
      /* Count mismatches, which are also from low qpos to high qpos */
      splice_qpos = segmenti_positions[i];
      while (nmismatches_i <= nmismatches_left && mismatch_positions_left[nmismatches_i] < splice_qpos) {
	nmismatches_i++;
      }
#ifdef DEBUG1
      if (nmismatches_i > nmismatches_allowed) {
	printf("(2) nmismatches_i for splice_qpos %d is >= %d (exceeds nmismatches_allowed)\n",
	       splice_qpos,nmismatches_i);
      } else {
	printf("(2) nmismatches_i for splice_qpos %d is %d\n",splice_qpos,nmismatches_i);
      }
#endif
    }
  }
    

  /* Right anchor (splice) */
  /* Advancing segmentj splice site from high qpos to low qpos.  Same direction for segmenti */
  /* All splicesites run from low qpos to high qpos */
  debug1(printf(">Right anchor -- splice on segmentj and indel on segmenti:\n"));
  nmismatches_j = 0;
  i = segmenti_nsites - 1;
  j = segmentj_nsites - 1;

  /* Count mismatches, which are also from high qpos to low qpos */
  splice_qpos = segmentj_positions[j];
  while (nmismatches_j <= nmismatches_right && mismatch_positions_right[nmismatches_j] >= splice_qpos) {
    nmismatches_j++;
  }
#ifdef DEBUG1
  if (nmismatches_j > nmismatches_allowed) {
    printf("(1) nmismatches_j for splice_qpos %d is >= %d (exceeds nmismatches_allowed)\n",
	   splice_qpos,nmismatches_j);
  } else {
    printf("(1) nmismatches_j for splice_qpos %d is %d\n",splice_qpos,nmismatches_j);
  }
#endif

  while (j >= 0 && nmismatches_j <= nmismatches_allowed) {
    if (segmentj_knowni[j] >= 0) {
      probj = 1.0;
    } else if (plusp == sense_forward_p) {
      probj = Maxent_hr_acceptor_prob(segmentj_left + splice_qpos,chroffset);
    } else {
      probj = Maxent_hr_antidonor_prob(segmentj_left + splice_qpos,chroffset);
    }
    debug1(printf("Probj at %d is %f\n",splice_qpos,probj));

    if (probj > SPLICE_PROB_LOW) {
      /* Backup to high qpos, and then advance to low qpos */
      while (i + 1 < segmenti_nsites && segmenti_positions[i+1] - splice_qpos <= max_deletionlen) {
	debug1(printf("Backing up i to %d because %d - splice_qpos %d < max_deletionlen %d\n",
		      i + 1,segmenti_positions[i+1],splice_qpos,max_insertionlen));
	i++;
      }

      /* Advance */
      while (i >= 0 && segmenti_nsites && segmenti_positions[i] - splice_qpos > max_deletionlen) {
	i--;
      }

      /* Deletions on segmenti */
      while (i >= 0 && segmenti_positions[i] > splice_qpos) {
	assert(segmenti_positions[i] - splice_qpos <= max_deletionlen);
	if (segmenti_knowni[i] >= 0) {
	  probi = 1.0;
	} else if (plusp == sense_forward_p) {
	  probi = Maxent_hr_donor_prob(segmenti_left + segmenti_positions[i],chroffset);
	} else {
	  probi = Maxent_hr_antiacceptor_prob(segmenti_left + segmenti_positions[i],chroffset);
	}
	debug1(printf("Deletion: probi at %d is %f\n",segmenti_positions[i],probi));

	if (probi > SPLICE_PROB_HIGH || (probi > SPLICE_PROB_LOW && probj > SPLICE_PROB_HIGH)) {
	  nindels = splice_qpos - segmenti_positions[i]; /* Should be negative */
	  debug1(printf("segmenti_left %u, segmentj_left %u, nindels %d\n",
			segmenti_left - chroffset,segmentj_left - chroffset,nindels));
	  debug1(printf("Trying deletion on segmenti of %d from %d to %d",nindels,segmenti_positions[i],splice_qpos));
	  /* Can re-use mismatch_positions_left because it is based on segmenti_left */
	  if ((indel_pos = Indel_resolve_middle_deletion(&nmismatches1,&nmismatches2,&ref_nmismatches1,&ref_nmismatches2,
							 univdiagonal_i,nindels,chrhigh,
							 /*re-use*/mismatch_positions_left,/*re-use*/nmismatches_left,
							 /*mismatch_positions_right*/NULL,/*nmismatches_right*/0,
							 /*ome*/genomebits,/*ome_alt*/genomebits_alt,
							 query_compress,pos5,/*pos3*/splice_qpos,
							 querylength,indelinfo,plusp,genestrand,
							 /*want_lowest_coordinate_p*/true)) < 0) {
	    debug1(printf(" => could not find deletion on segmenti\n"));
	  } else {
	    assert(indel_pos > pos5);
	    assert(indel_pos < splice_qpos);
	    /* support_indel = splice_qpos - indel_pos; */
	    nmismatches_i = nmismatches1;
	    nmismatches_indel = nmismatches2; /* From indel to splice */
	    debug1(printf(" => indel_pos %d, splice_qpos %d, mismatches_i %d, mismatches_indel %d, nmismatches_j %d, prob %f",
			  indel_pos,splice_qpos,nmismatches_i,nmismatches_indel,nmismatches_j,probi+probj));
	    if ((prob = probi + probj) > best_prob) {
	      debug1(printf(" **"));
	      *best_nindels = -nindels; /* Flip sign */
	      *best_indel_pos = indel_pos;
	      *best_nmismatches_i = *best_ref_nmismatches_i = nmismatches_i;
	      *best_nmismatches_indel = *best_ref_nmismatches_indel = nmismatches_indel;
	      *best_nmismatches_j = *best_ref_nmismatches_j = nmismatches_j;
	      best_splice_qpos = splice_qpos;
	      /* best_knowni_i = segmenti_knowni[i]; */
	      /* best_knowni_j = segmentj_knowni[j]; */
	      best_probi = probi;
	      best_probj = probj;
	      best_prob = prob;
	      best_nmismatches = nmismatches_indel + nmismatches_i + nmismatches_j;
	    } else if (prob > best_prob - PROB_SLOP &&
		       (nmismatches = nmismatches_indel + nmismatches_i + nmismatches_j) < best_nmismatches) {
	      debug1(printf(" **"));
	      *best_nindels = -nindels; /* Flip sign */
	      *best_indel_pos = indel_pos;
	      *best_nmismatches_i = *best_ref_nmismatches_i = nmismatches_i;
	      *best_nmismatches_indel = *best_ref_nmismatches_indel = nmismatches_indel;
	      *best_nmismatches_j = *best_ref_nmismatches_j = nmismatches_j;
	      best_splice_qpos = splice_qpos;
	      /* best_knowni_i = segmenti_knowni[i]; */
	      /* best_knowni_j = segmentj_knowni[j]; */
	      best_probi = probi;
	      best_probj = probj;
	      best_prob = prob;
	      best_nmismatches = nmismatches;
	    }
	    debug1(printf("\n"));
	  }
	}

	i--;
      }

      if (i >= 0 && segmenti_positions[i] == splice_qpos) {
	/* Splice without indel */
	i--;
      }

      /* Insertions on segmenti */
      while (i >= 0 && splice_qpos - segmenti_positions[i] <= max_insertionlen) {
	if (segmenti_knowni[i] >= 0) {
	  probi = 1.0;
	} else if (plusp == sense_forward_p) {
	  probi = Maxent_hr_donor_prob(segmenti_left + segmenti_positions[i],chroffset);
	} else {
	  probi = Maxent_hr_antiacceptor_prob(segmenti_left + segmenti_positions[i],chroffset);
	}
	debug1(printf("Insertion: probi at %d is %f\n",segmenti_positions[i],probi));

	if (probi > SPLICE_PROB_HIGH || (probi > SPLICE_PROB_LOW && probj > SPLICE_PROB_HIGH)) {
	  nindels = splice_qpos - segmenti_positions[i];
	  debug1(printf("segmenti_left %u, segmentj_left %u, nindels %d\n",
			segmenti_left - chroffset,segmentj_left - chroffset,nindels));
	  debug1(printf("Trying insertion on segmenti of %d from %d to %d",nindels,segmenti_positions[i],splice_qpos));
	  /* Can re-use mismatch_positions_left because it is based on segmenti_left */
	  if ((indel_pos = Indel_resolve_middle_insertion(&nmismatches1,&nmismatches2,&ref_nmismatches1,&ref_nmismatches2,
							  univdiagonal_i,nindels,chrhigh,
							  /*re-use*/mismatch_positions_left,/*re-use*/nmismatches_left,
							  /*mismatch_positions_right*/NULL,/*nmismatches_right*/0,
							  /*ome*/genomebits,/*ome_alt*/genomebits_alt,
							  query_compress,pos5,/*pos3*/splice_qpos,
							  querylength,indelinfo,plusp,genestrand,
							  /*want_lowest_coordinate_p*/true)) < 0) {
	    debug1(printf(" => could not find insertion on segmenti\n"));
	  } else {
	    assert(indel_pos > pos5);
	    assert(indel_pos + nindels < splice_qpos);
	    /* support_indel = splice_qpos - (indel_pos + nindels); */
	    nmismatches_i = nmismatches1;
	    nmismatches_indel = nmismatches2; /* From indel to splice */
	    debug1(printf(" => indel_pos %d, splice_qpos %d, mismatches_i %d, mismatches_indel %d, mismatches_j %d, prob %f",
			  indel_pos,splice_qpos,nmismatches_i,nmismatches_indel,nmismatches_j,probi+probj));
	    if ((prob = probi + probj) > best_prob) {
	      debug1(printf(" **"));
	      *best_nindels = -nindels; /* Flip sign */
	      *best_indel_pos = indel_pos;
	      *best_nmismatches_i = *best_ref_nmismatches_i = nmismatches_i;
	      *best_nmismatches_indel = *best_ref_nmismatches_indel = nmismatches_indel;
	      *best_nmismatches_j = *best_ref_nmismatches_j = nmismatches_j;
	      best_splice_qpos = splice_qpos;
	      /* best_knowni_i = segmenti_knowni[i]; */
	      /* best_knowni_j = segmentj_knowni[j]; */
	      best_probi = probi;
	      best_probj = probj;
	      best_prob = prob;
	      best_nmismatches = nmismatches_indel + nmismatches_i + nmismatches_j;
	    } else if (prob > best_prob - PROB_SLOP &&
		       (nmismatches = nmismatches_indel + nmismatches_i + nmismatches_j) < best_nmismatches) {
	      debug1(printf(" **"));
	      *best_nindels = -nindels; /* Flip sign */
	      *best_indel_pos = indel_pos;
	      *best_nmismatches_i = *best_ref_nmismatches_i = nmismatches_i;
	      *best_nmismatches_indel = *best_ref_nmismatches_indel = nmismatches_indel;
	      *best_nmismatches_j = *best_ref_nmismatches_j = nmismatches_j;
	      best_splice_qpos = splice_qpos;
	      /* best_knowni_i = segmenti_knowni[i]; */
	      /* best_knowni_j = segmentj_knowni[j]; */
	      best_probi = probi;
	      best_probj = probj;
	      best_prob = prob;
	      best_nmismatches = nmismatches;
	    }
	    debug1(printf("\n"));
	  }
	}

	i--;
      }

    }
      
    if (--j >= 0) {
      /* Count mismatches, which are also from high qpos to low qpos */
      splice_qpos = segmentj_positions[j];
      while (nmismatches_j <= nmismatches_right && mismatch_positions_right[nmismatches_j] >= splice_qpos) {
	nmismatches_j++;
      }
#ifdef DEBUG1
      if (nmismatches_j > nmismatches_allowed) {
	printf("(2) nmismatches_j for splice_qpos %d is >= %d (exceeds nmismatches_allowed)\n",
	       splice_qpos,nmismatches_j);
      } else {
	printf("(2) nmismatches_j for splice_qpos %d is %d\n",splice_qpos,nmismatches_j);
      }
#endif
    }
  }
  
  if (plusp == sense_forward_p) {
    *best_donor_prob = best_probi;
    *best_acceptor_prob = best_probj;
  } else {
    *best_donor_prob = best_probj;
    *best_acceptor_prob = best_probi;
  }

  debug1(printf("spliceindel_resolve returning splice_qpos %d, indel_pos %d\n",best_splice_qpos,*best_indel_pos));
  return best_splice_qpos;
}


static int
atypical_splice (int *best_nmismatches_i, int *best_nmismatches_j,
		 int *best_ref_nmismatches_i, int *best_ref_nmismatches_j,
		 double *best_donor_prob, double *best_acceptor_prob,

		 Univcoord_T univdiagonal_i, Univcoord_T univdiagonal_j,
		 bool plusp, Univcoord_T chroffset, int pos5, int pos3, int querylength,
		 Spliceinfo_T spliceinfo, int nmismatches_left, int nmismatches_right,
		 bool sense_forward_p, int nmismatches_allowed) {
  int splice_qpos_low, splice_qpos_high;
  int *mismatch_positions_left, *mismatch_positions_right;
  int lefti, righti;

  int best_splice_qpos, splice_qpos;

  double best_prob, prob, probi, probj;
  Univcoord_T segmenti_left, segmentj_left;


  segmenti_left = univdiagonal_i - querylength;
  segmentj_left = univdiagonal_j - querylength;


  debug1(printf("Entered atypical_splice with pos5 %d, pos3 %d\n",pos5,pos3));

  mismatch_positions_left = spliceinfo->mismatch_positions_left; /* Use values computed previously */
  mismatch_positions_right = spliceinfo->mismatch_positions_right; /* Use values computed previously */

  /* Find low bound for splice pos based on nmismatches_right */
  if (nmismatches_right < nmismatches_allowed) {
    splice_qpos_low = mismatch_positions_right[nmismatches_right];
  } else {
    splice_qpos_low = mismatch_positions_right[nmismatches_allowed];
    debug1(printf("splice_qpos_low is determined by nmismatches_allowed %d => %d\n",
		  nmismatches_allowed,splice_qpos_low));
  }
  if (splice_qpos_low < pos5 + 1) {
    splice_qpos_low = pos5 + 1;
  }

  debug1(printf("  Splice low bound: %d\n",splice_qpos_low));

  /* Find high bound for splice pos based on nmismatches_left */
  if (nmismatches_left < nmismatches_allowed) {
    splice_qpos_high = mismatch_positions_left[nmismatches_left];
  } else {
    splice_qpos_high = mismatch_positions_left[nmismatches_allowed];
    debug1(printf("splice_qpos_high is determined by nmismatches_allowed %d => %d\n",
		  nmismatches_allowed,splice_qpos_high));
  }
  if (splice_qpos_high > pos3 - 1) {
    splice_qpos_high = pos3 - 1;
  }
  debug1(printf("  Splice high bound: %d\n",splice_qpos_high));

  if (splice_qpos_low >= splice_qpos_high) {
    *best_nmismatches_i = *best_nmismatches_j = -1; /* Indicates that calling procedure needs to compute numbers of mismatches  */
    return -1;
  }

  best_prob = 0.0;
  if (plusp == sense_forward_p) {
    /* plus sense or minus antisense */
    for (splice_qpos = splice_qpos_low; splice_qpos < splice_qpos_high; splice_qpos++) {
      probi = Maxent_hr_donor_prob(segmenti_left + splice_qpos,chroffset);
      probj = Maxent_hr_acceptor_prob(segmentj_left + splice_qpos,chroffset);
      debug1(printf("  At splice_qpos %d, watson probs are %f and %f\n",splice_qpos,probi,probj));
      if ((prob = probi + probj) > best_prob) {
	best_splice_qpos = splice_qpos;
	*best_donor_prob = probi;
	*best_acceptor_prob = probj;
	best_prob = prob;
      }
    }
   
  } else {
    /* minus sense or plus antisense */
    for (splice_qpos = splice_qpos_low; splice_qpos < splice_qpos_high; splice_qpos++) {
      probi = Maxent_hr_antiacceptor_prob(segmenti_left + splice_qpos,chroffset);
      probj = Maxent_hr_antidonor_prob(segmentj_left + splice_qpos,chroffset);
      debug1(printf("  At splice_qpos %d, crick probs are %f and %f\n",splice_qpos,probi,probj));
      if ((prob = probi + probj) > best_prob) {
	best_splice_qpos = splice_qpos;
	*best_acceptor_prob = probi;
	*best_donor_prob = probj;
	best_prob = prob;
      }
    }
  }


  lefti = 0;
  while (lefti < nmismatches_left && mismatch_positions_left[lefti] < best_splice_qpos) {
    lefti++;
  }
  *best_nmismatches_i = *best_ref_nmismatches_i = lefti;
    
  righti = 0;
  while (righti < nmismatches_right && mismatch_positions_right[righti] >= best_splice_qpos) {
    righti++;
  }
  *best_nmismatches_j = *best_ref_nmismatches_j = righti;

  return best_splice_qpos;
}


#if defined(DEBUG1) || defined(DEBUG2)
static void
print_diffs (char *string1, char *string2, int querylength) {
  int i;

  for (i = 0; i < querylength; i++) {
    if (string1[i] == string2[i]) {
      printf("|");
    } else {
      printf(" ");
    }
  }
}
#endif


/* Needs to be at least 3 to handle indels near splice site */
#define EXTRA_NMISMATCHES 3

/* Note: knowni holds joffset + j + 1, so 0 represents no known site
   and values greater than 0 represent a known site.  Need to subtract
   1 to obtain joffset + j. */

/* We set check_support_p to be false for inner resolve, where we can
   expect short pieces, and have some certainty in the short
   concordant region that they are correct */
int
Splice_resolve (Univcoord_T *middle_univdiagonal, int *splice_qpos_i, int *splice_qpos_j,
		int *best_nindels, int *best_indel_pos,
		int *best_nmismatches_i, int *nmismatches_middle, int *best_nmismatches_j,
		int *best_nmismatches_indel,

		int *best_ref_nmismatches_i, int *ref_nmismatches_middle, int *best_ref_nmismatches_j,
		int *best_ref_nmismatches_indel, double *best_donor_prob, double *best_acceptor_prob,

		Univcoord_T univdiagonal_i, Univcoord_T univdiagonal_j,
		Compress_T query_compress, bool plusp, Univcoord_T chroffset, Univcoord_T chrhigh,
		     
		int pos5, int pos3, int querylength,
		Indelinfo_T indelinfo, Spliceinfo_T spliceinfo, Knownsplicing_T knownsplicing,
		bool sense_forward_p, int genestrand, int max_insertionlen, int max_deletionlen,
		bool salvagep, bool check_support_p) {

  int splice_qpos_low, splice_qpos_high;
  int *mismatch_positions_left, *mismatch_positions_right;
  int nmismatches_left, nmismatches_right;

  int best_splice_qpos, splice_qpos, i, j;
  Univcoord_T *endpoints;
  uint64_t low_rank, high_rank, next_rank, rank;

  int best_nmismatches, nmismatches, segmenti_nmismatches, segmentj_nmismatches;
  double best_prob, best_probi, best_probj, donor_prob, acceptor_prob;

  int segmenti_nsites, segmentj_nsites;
  int *segmenti_positions, *segmentj_positions;
  int *segmenti_knowni, *segmentj_knowni;

  int adj_supporti, adj_supportj, supporti, supportj;
  Univcoord_T segmenti_left, segmentj_left;
  
  int nmismatches_to_trimpos;


#ifdef DEBUG1
  char *gbuffer1, *gbuffer2;
  static int ncalls = 0;
#endif

#ifdef DEBUG1
  segmenti_left = univdiagonal_i - querylength;
  segmentj_left = univdiagonal_j - querylength;

  printf("Splice_resolve, plusp %d, compress_fwdp %d, sense_forward_p %d, call %d: Getting genome at lefti %u [%u] and leftj %u [%u] (diff: %d), range %d..%d, salvagep %d, check_support_p %d\n",
	 plusp,Compress_fwdp(query_compress),sense_forward_p,++ncalls,
	 segmenti_left,segmenti_left - chroffset,segmentj_left,segmentj_left - chroffset,
	 segmentj_left-segmenti_left,pos5,pos3,salvagep,check_support_p);
#endif
  assert(Compress_fwdp(query_compress) == plusp);


#ifdef TRIM_AT_CHROMOSOME_BOUNDS
  Univcoord_T univdiagonali, univdiagonalj;
  pos5 = (univdiagonal_i + pos5 >= chroffset + querylength) ? pos5 : (int) (chroffset - segmenti_left);
  pos3 = (univdiagonal_j + pos3 <= chrhigh + querylength) ? pos3 : (int) (chrhigh - segmentj_left);
#endif


  /* Require separation from endpoints */
#if 0
  splice_qpos_start = pos5 + 1;
  splice_qpos_end = pos3 - 1;
  if (splice_qpos_start < min_shortend) {
    splice_qpos_start = min_shortend;
  }
  if (splice_qpos_end > querylength - min_shortend) {
    splice_qpos_end = querylength - min_shortend;
  }
#endif

  *middle_univdiagonal = (Univcoord_T) 0;

  /* Determine feasibility of a splice */

  /* New method, different from relying on nmismatches_allowed */
  mismatch_positions_left = spliceinfo->mismatch_positions_left; /* Use allocated memory */
  mismatch_positions_right = spliceinfo->mismatch_positions_right; /* Use allocated memory */

#ifdef USE_NMISMATCHES_ALLOWED
  debug1(printf("nmismatches_allowed is %d.  Calling Genomebits_mismatches_fromleft over %d..%d\n",
		nmismatches_allowed,pos5,pos3));
  /* Don't use nmismatches_allowed, because we want to count all mismatches for proper accounting and decision-making */
  nmismatches_left = Genomebits_mismatches_fromleft(mismatch_positions_left,/*nmismatches_allowed*/querylength,
						    /*ome*/genomebits,/*ome_alt*/genomebits_alt,
						    query_compress,univdiagonal_i,querylength,
						    pos5,pos3,plusp,genestrand);

  debug1(printf("nmismatches_allowed is %d.  Calling Genomebits_mismatches_fromright over %d..%d\n",
		nmismatches_allowed,pos5,pos3));

  /* Don't use nmismatches_allowed, because we want to count all mismatches for proper accounting and decision-making */
  nmismatches_right = Genomebits_mismatches_fromright(mismatch_positions_right,/*nmismatches_allowed*/querylength,
						  /*ome*/genomebits,/*ome_alt*/genomebits_alt,
						  query_compress,univdiagonal_j,querylength,
						  pos5,pos3,plusp,genestrand);

  /* assert(nmismatches_left <= nmismatches_allowed + 1); -- Not valid when using querylength */
  /* assert(nmismatches_right <= nmismatches_allowed + 1); -- Not valid when using querylength */

  debug1(
	 printf("(2) %d mismatches on left from %d to %d at:",nmismatches_left,pos5,pos3);
	 for (i = 0; i <= nmismatches_left; i++) {
	   printf(" %d",mismatch_positions_left[i]);
	 }
	 printf("\n");
	 );

  debug1(
	 printf("(2) %d mismatches on right from %d to %d at:",nmismatches_right,pos3,pos5);
	 for (i = 0; i <= nmismatches_right; i++) {
	   printf(" %d",mismatch_positions_right[i]);
	 }
	 printf("\n");
	 );

  /* Find low bound for splice pos based on nmismatches_right */
  if (nmismatches_right < nmismatches_allowed) {
    splice_qpos_low = mismatch_positions_right[nmismatches_right];
  } else {
    splice_qpos_low = mismatch_positions_right[nmismatches_allowed];
  }

  /* Find high bound for splice pos based on nmismatches_left */
  if (nmismatches_left < nmismatches_allowed) {
    splice_qpos_high = mismatch_positions_left[nmismatches_left];
  } else {
    splice_qpos_high = mismatch_positions_left[nmismatches_allowed];
  }

#else
  splice_qpos_high = Spliceends_trim_qend_nosplice(&nmismatches_to_trimpos,&nmismatches_left,mismatch_positions_left,
						   query_compress,genomebits,genomebits_alt,
						   univdiagonal_i,querylength,pos5,pos3,plusp,genestrand) + EXTRA_NMISMATCHES;
  debug1(
	 printf("(3) %d mismatches on left from %d to %d at:",nmismatches_left,pos5,pos3);
	 for (i = 0; i <= nmismatches_left; i++) {
	   printf(" %d",mismatch_positions_left[i]);
	 }
	 printf("\n");
	 );

  splice_qpos_low = Spliceends_trim_qstart_nosplice(&nmismatches_to_trimpos,&nmismatches_right,mismatch_positions_right,
						    query_compress,genomebits,genomebits_alt,
						    univdiagonal_j,querylength,pos5,pos3,plusp,genestrand) - EXTRA_NMISMATCHES;

  debug1(
	 printf("(3) %d mismatches on right from %d to %d at:",nmismatches_right,pos3,pos5);
	 for (i = 0; i <= nmismatches_right; i++) {
	   printf(" %d",mismatch_positions_right[i]);
	 }
	 printf("\n");
	 );
#endif

  if (splice_qpos_low < pos5 + 1) {
    splice_qpos_low = pos5 + 1;
  }
  debug1(printf("  Splice low bound: %d\n",splice_qpos_low));

  if (splice_qpos_high > pos3 - 1) {
    splice_qpos_high = pos3 - 1;
  }
  debug1(printf("  Splice high bound: %d\n",splice_qpos_high));


#ifdef DEBUG1
  gbuffer1 = (char *) CALLOC(querylength+1,sizeof(char));
  gbuffer2 = (char *) CALLOC(querylength+1,sizeof(char));
  Genome_fill_buffer(univdiagonal_i - querylength,querylength,gbuffer1);
  Genome_fill_buffer(univdiagonal_j - querylength,querylength,gbuffer2);
  char *queryseq = Compress_queryseq(query_compress,querylength);

  printf("Splice_resolve, plusp %d: Getting genome at left %llu and %llu\n",
	 plusp,(unsigned long long) segmenti_left,(unsigned long long) segmentj_left);
  printf("g1: %s\n",gbuffer1);
  printf("    ");
  print_diffs(gbuffer1,queryseq,querylength);
  printf("\n");
  printf("q:  %s\n",queryseq);
  printf("    ");
  print_diffs(gbuffer2,queryseq,querylength);
  printf("\n");
  printf("g2: %s\n",gbuffer2);
  FREE(gbuffer2);
  FREE(gbuffer1);
#endif

  if (splice_qpos_low >= splice_qpos_high) {
    /* The two ends cannot meet */
    if (knownsplicing == NULL) {
      *best_nmismatches_i = *best_nmismatches_j = -1; /* Indicates that calling procedure needs to compute numbers of mismatches  */
      return -1;
    } else {
      /* Perhaps there is an exon in the middle */
      return find_middle_exon(&(*middle_univdiagonal),&(*splice_qpos_i),&(*splice_qpos_j),
			      &(*best_nmismatches_i),&(*nmismatches_middle),&(*best_nmismatches_j),
			      &(*best_ref_nmismatches_i),&(*ref_nmismatches_middle),&(*best_ref_nmismatches_j),
			      &(*best_donor_prob),&(*best_acceptor_prob),
			      univdiagonal_i,univdiagonal_j,pos5,pos3,
			      /*splice_qpos_5*/splice_qpos_high,/*splice_qpos_3*/splice_qpos_low,querylength,
			      /*re-use*/mismatch_positions_left,/*re-use*/mismatch_positions_right,
			      query_compress,nmismatches_left,nmismatches_right,
			      spliceinfo,knownsplicing,plusp,sense_forward_p,genestrand);
    }
  }


/************************************************************************
 *   Known splicing
 ************************************************************************/

  segmenti_left = univdiagonal_i - querylength;
  segmentj_left = univdiagonal_j - querylength;

  best_splice_qpos = -1;
  if (plusp == sense_forward_p) {
    /* plus sense or minus antisense */
    segmenti_nsites = segmentj_nsites = 0;
    /* segmenti_positions = spliceinfo->segmenti_qpos_alloc; */
    /* segmentj_positions = spliceinfo->segmentj_qpos_alloc; */
    segmenti_positions = spliceinfo->segmenti_knownpos;
    segmentj_positions = spliceinfo->segmentj_knownpos;
    segmenti_knowni = spliceinfo->segmenti_knowni;
    segmentj_knowni = spliceinfo->segmentj_knowni;

    if (knownsplicing != NULL) {
      endpoints = Knownsplicing_donors(&low_rank,&high_rank,knownsplicing,
				       univdiagonal_i,querylength,splice_qpos_low,splice_qpos_high);
      debug1(printf("Knownsplicing donors at %u+%d..%d yields low_rank %lu to high_rank %lu\n",
		    segmenti_left,splice_qpos_low,splice_qpos_high,low_rank,high_rank));
      /* Collapse duplicates because we don't care about partners */
      rank = low_rank;
      while (rank < high_rank) {
	debug4s(printf("Setting known donor %d for segmenti at %u..%u\n",(int) rank,endpoints[2*rank],endpoints[2*rank+1]));
	segmenti_knowni[segmenti_nsites] = (int) rank;
	segmenti_positions[segmenti_nsites] = endpoints[2*rank] - segmenti_left;

	next_rank = rank + 1;
	while (next_rank < high_rank && endpoints[2*next_rank] == endpoints[2*rank]) {
	  next_rank += 1;
	}
	rank = next_rank;
      }

#ifdef DEBUG1
      printf("Found %d known donori sites:",segmenti_nsites);
      for (i = 0; i < segmenti_nsites; i++) {
	printf(" %d",segmenti_positions[i]);
      }
      printf("\n");
#endif

      endpoints = Knownsplicing_acceptors(&low_rank,&high_rank,knownsplicing,
					  univdiagonal_j,querylength,splice_qpos_low,splice_qpos_high);
      debug1(printf("Knownsplicing acceptors at %u+%d..%d yields low_rank %lu to high_rank %lu\n",
		    segmentj_left,splice_qpos_low,splice_qpos_high,low_rank,high_rank));
      /* Collapse duplicates because we don't care about partners */
      rank = low_rank;
      while (rank < high_rank) {
	debug4s(printf("Setting known acceptor %d for segmentj at %u..%u\n",(int) rank,endpoints[2*rank],endpoints[2*rank+1]));
	segmentj_knowni[segmentj_nsites] = (int) rank;
	segmentj_positions[segmentj_nsites++] = endpoints[2*rank] - segmentj_left;

	next_rank = rank + 1;
	while (next_rank < high_rank && endpoints[2*next_rank] == endpoints[2*rank]) {
	  next_rank += 1;
	}
	rank = next_rank;
      }
#ifdef DEBUG1
      printf("Found %d known acceptorj sites:",segmentj_nsites);
      for (i = 0; i < segmentj_nsites; i++) {
	printf(" %d",segmentj_positions[i]);
      }
      printf("\n");
#endif
    }

    if (novelsplicingp == true) {
    /* plus sense or minus antisense */
      segmenti_positions[segmenti_nsites] = querylength; /* Needed to terminate search in Genome_sites */
      segmenti_nsites = Genome_donor_positions(segmenti_positions = spliceinfo->segmenti_qpos_alloc,
					       segmenti_knowni = spliceinfo->segmenti_knowni_alloc,
					       spliceinfo->segmenti_knownpos,
					       spliceinfo->segmenti_knowni,
					       segmenti_left,splice_qpos_low,splice_qpos_high);

#ifdef DEBUG1
      printf("Found %d donori sites:",segmenti_nsites);
      for (i = 0; i < segmenti_nsites; i++) {
	printf(" %d",segmenti_positions[i]);
	if (segmenti_knowni[i] >= 0) {
	  printf(" [#%d]",segmenti_knowni[i]);
	} else {
	  printf(" (%.6f)",Maxent_hr_donor_prob(segmenti_left + segmenti_positions[i],chroffset));
	}
      }
      printf("\n");
#endif

      segmentj_positions[segmentj_nsites] = querylength; /* Needed to terminate search in Genome_sites */
      segmentj_nsites = Genome_acceptor_positions(segmentj_positions = spliceinfo->segmentj_qpos_alloc,
						  segmentj_knowni = spliceinfo->segmentj_knowni_alloc,
						  spliceinfo->segmentj_knownpos,
						  spliceinfo->segmentj_knowni,
						  segmentj_left,splice_qpos_low,splice_qpos_high);
#ifdef DEBUG1
      printf("Found %d acceptorj sites:",segmentj_nsites);
      for (i = 0; i < segmentj_nsites; i++) {
	printf(" %d",segmentj_positions[i]);
	if (segmentj_knowni[i] >= 0) {
	  printf(" [#%d]",segmentj_knowni[i]);
	} else {
	  printf(" (%.6f)",Maxent_hr_acceptor_prob(segmentj_left + segmentj_positions[i],chroffset));
	}
      }
      printf("\n");
#endif
    }


    if (segmenti_nsites == 0 || segmentj_nsites == 0) {
      debug1(printf("Splice sites are missing on one side, so returning -1\n"));
      *best_nmismatches_i = *best_nmismatches_j = -1; /* Indicates that calling procedure needs to compute numbers of mismatches  */
      return -1;
    } else {
      best_splice_qpos = -1;
      best_prob = 0.0;
      best_nmismatches = pos3 - pos5;
      *best_donor_prob = *best_acceptor_prob = 0.0;
    }

    /* Try for no indel */
    debug1(printf("Looking for splice only\n"));
    /* segmenti_positions and segmentj_positions are ascending */
    /* mismatch_positions_i are ascending, but mismatch_positions_right are descending */
    segmenti_nmismatches = 0;
    segmentj_nmismatches = nmismatches_right;
    i = j = 0;

    while (i < segmenti_nsites && j < segmentj_nsites) {
      debug1(printf("i [%d/%d]: %d and j [%d/%d]: %d\n",
		    i,segmenti_nsites,segmenti_positions[i],j,segmentj_nsites,segmentj_positions[j]));
      if ((splice_qpos = segmenti_positions[i]) < segmentj_positions[j]) {
	i++;
	
      } else if (splice_qpos > segmentj_positions[j]) {
	j++;
	
      } else {
	debug1(printf("splice matches at %d\n",splice_qpos));
	while (segmenti_nmismatches <= nmismatches_left && mismatch_positions_left[segmenti_nmismatches] < splice_qpos) {
	  segmenti_nmismatches++;
	}
	while (segmentj_nmismatches - 1 >= 0 && mismatch_positions_right[segmentj_nmismatches - 1] < splice_qpos) {
	  segmentj_nmismatches--;
	}

#if 0
	/* supporti = splice_qpos - pos5; */
	/* supportj = pos3 - splice_qpos; */
	debug1(printf("Considering candidate splice_qpos %d with supporti %d and %d mismatches, supportj %d and %d mismatches =>",
		      splice_qpos,supporti,segmenti_nmismatches,supportj,segmentj_nmismatches));
	if (supporti - 4*segmenti_nmismatches <= 0) {
	  debug1(printf(" no\n"));
	} else if (supportj - 4*segmentj_nmismatches <= 0) {
	  debug1(printf(" no\n"));
	} else {
	  debug1(printf(" yes\n"));
	  candidates = Intlist_push(candidates,splice_qpos);
	}
#endif

	debug1(printf("Evaluating known plus splice pos %d\n",splice_qpos));
	debug1(printf("%d mismatches on segmenti (%d..%d)\n",segmenti_nmismatches,pos5,splice_qpos));
	debug1(printf("%d mismatches on segmentj (%d..%d)\n",segmentj_nmismatches,splice_qpos,pos3));
	
	if (segmenti_knowni[i] >= 0) {
	  donor_prob = 1.0;
	} else {
	  donor_prob = Maxent_hr_donor_prob(segmenti_left + segmenti_positions[i],chroffset);
	}
	if (segmentj_knowni[j] >= 0) {
	  acceptor_prob = 1.0;
	} else {
	  acceptor_prob = Maxent_hr_acceptor_prob(segmentj_left + segmentj_positions[j],chroffset);
	}

	if (0 && salvagep == false && (donor_prob < MIN_PROB || acceptor_prob < MIN_PROB)) {
	  /* Skip */
	} else if ((nmismatches = segmenti_nmismatches + segmentj_nmismatches) < best_nmismatches) {
	  best_nmismatches = nmismatches;
	  best_splice_qpos = splice_qpos;
	  *best_nmismatches_i = *best_ref_nmismatches_i = segmenti_nmismatches;
	  *best_nmismatches_j = *best_ref_nmismatches_j = segmentj_nmismatches;
	  *best_donor_prob = donor_prob;
	  *best_acceptor_prob = acceptor_prob;
	  best_prob = donor_prob + acceptor_prob;

	} else if (nmismatches == best_nmismatches) {
	  if (donor_prob + acceptor_prob > best_prob) {
	    best_splice_qpos = splice_qpos;
	    *best_nmismatches_i = *best_ref_nmismatches_i = segmenti_nmismatches;
	    *best_nmismatches_j = *best_ref_nmismatches_j = segmentj_nmismatches;
	    *best_donor_prob = donor_prob;
	    *best_acceptor_prob = acceptor_prob;
	    best_prob = donor_prob + acceptor_prob;
	  }
	}
	i++; j++;
      }
    }

  } else {
    /* minus sense or plus antisense */
    segmenti_nsites = segmentj_nsites = 0;
    /* segmenti_positions = spliceinfo->segmenti_qpos_alloc; */
    /* segmentj_positions = spliceinfo->segmentj_qpos_alloc; */
    segmenti_positions = spliceinfo->segmenti_knownpos;
    segmentj_positions = spliceinfo->segmentj_knownpos;
    segmenti_knowni = spliceinfo->segmenti_knowni;
    segmentj_knowni = spliceinfo->segmentj_knowni;

    if (knownsplicing != NULL) {
      endpoints = Knownsplicing_antiacceptors(&low_rank,&high_rank,knownsplicing,
					      univdiagonal_i,querylength,splice_qpos_low,splice_qpos_high);
      debug1(printf("Knownsplicing antiacceptors at %u+%d..%d yields low_rank %lu to high_rank %lu\n",
		    segmenti_left,splice_qpos_low,splice_qpos_high,low_rank,high_rank));
      /* Collapse duplicates because we don't care about partners */
      rank = low_rank;
      while (rank < high_rank) {
	debug4s(printf("Setting known antiacceptor %d for segmenti at %u..%u\n",(int) rank,endpoints[2*rank],endpoints[2*rank+1]));
	segmenti_knowni[segmenti_nsites] = (int) rank;
	segmenti_positions[segmenti_nsites++] = endpoints[2*rank] - segmenti_left;

	next_rank = rank + 1;
	while (next_rank < high_rank && endpoints[2*next_rank] == endpoints[2*rank]) {
	  next_rank += 1;
	}
	rank = next_rank;
      }
#ifdef DEBUG1
      printf("Found %d known antiacceptori sites:",segmenti_nsites);
      for (i = 0; i < segmenti_nsites; i++) {
	printf(" %d",segmenti_positions[i]);
	printf("\n");
      }
#endif

      endpoints = Knownsplicing_antidonors(&low_rank,&high_rank,knownsplicing,
					   univdiagonal_j,querylength,splice_qpos_low,splice_qpos_high);
      debug1(printf("Knownsplicing antidonors at %u+%d..%d yields low_rank %lu to high_rank %lu\n",
		    segmentj_left,splice_qpos_low,splice_qpos_high,low_rank,high_rank));
      /* Collapse duplicates because we don't care about partners */
      rank = low_rank;
      while (rank < high_rank) {
	debug4s(printf("Setting known antidonor %d for segmentj at %u..%u\n",(int) rank,endpoints[2*rank],endpoints[2*rank+1]));
	segmentj_knowni[segmentj_nsites] = (int) rank;
	segmentj_positions[segmentj_nsites++] = endpoints[2*rank] - segmentj_left;

	next_rank = rank + 1;
	while (next_rank < high_rank && endpoints[2*next_rank] == endpoints[2*rank]) {
	  next_rank += 1;
	}
	rank = next_rank;
      }

#ifdef DEBUG1
      printf("Found %d known antidonorj sites:",segmentj_nsites);
      for (i = 0; i < segmentj_nsites; i++) {
	printf(" %d",segmentj_positions[i]);
      }
      printf("\n");
#endif
    }

    if (novelsplicingp == true) {
      segmenti_positions[segmenti_nsites] = querylength; /* Needed to terminate search in Genome_sites */
      segmenti_nsites = Genome_antiacceptor_positions(segmenti_positions = spliceinfo->segmenti_qpos_alloc,
						      segmenti_knowni = spliceinfo->segmenti_knowni_alloc,
						      spliceinfo->segmenti_knownpos,
						      spliceinfo->segmenti_knowni,
						      segmenti_left,splice_qpos_low,splice_qpos_high);
#ifdef DEBUG1
      printf("Found %d antiacceptori sites:",segmenti_nsites);
      for (i = 0; i < segmenti_nsites; i++) {
	printf(" %d",segmenti_positions[i]);
	if (segmenti_knowni[i] >= 0) {
	  printf(" [#%d]",segmenti_knowni[i]);
	} else {
	  printf(" (%.6f)",Maxent_hr_antiacceptor_prob(segmenti_left + segmenti_positions[i],chroffset));
	}
      }
      printf("\n");
#endif

      segmentj_positions[segmentj_nsites] = querylength; /* Needed to terminate search in Genome_sites */
      segmentj_nsites = Genome_antidonor_positions(segmentj_positions = spliceinfo->segmentj_qpos_alloc,
						   segmentj_knowni = spliceinfo->segmentj_knowni_alloc,
						   spliceinfo->segmentj_knownpos,
						   spliceinfo->segmentj_knowni,
						   segmentj_left,splice_qpos_low,splice_qpos_high);

#ifdef DEBUG1
      printf("Found %d antidonorj sites:",segmentj_nsites);
      for (i = 0; i < segmentj_nsites; i++) {
	printf(" %d",segmentj_positions[i]);
	if (segmentj_knowni[i] >= 0) {
	  printf(" [#%d]",segmentj_knowni[i]);
	} else {
	  printf(" (%.6f)",Maxent_hr_antidonor_prob(segmentj_left + segmentj_positions[i],chroffset));
	}
      }
      printf("\n");
#endif
    }


    if (segmenti_nsites == 0 || segmentj_nsites == 0) {
      debug1(printf("Splice sites are missing on one side, so returning -1\n"));
      *best_nmismatches_i = *best_nmismatches_j = -1; /* Indicates that calling procedure needs to compute numbers of mismatches  */
      return -1;
    } else {
      best_splice_qpos = -1;
      best_prob = 0.0;
      best_nmismatches = pos3 - pos5;
      *best_donor_prob = *best_acceptor_prob = 0.0;
    }

    /* Try for no indel */
    debug1(printf("Looking for splice only\n"));
    /* segmenti_positions and segmentj_positions are ascending */
    /* mismatch_positions_i are ascending, but mismatch_positions_right are descending */
    segmenti_nmismatches = 0;
    segmentj_nmismatches = nmismatches_right;
    i = j = 0;

    while (i < segmenti_nsites && j < segmentj_nsites) {
      debug1(printf("i [%d/%d]: %d and j [%d/%d]: %d\n",
		    i,segmenti_nsites,segmenti_positions[i],j,segmentj_nsites,segmentj_positions[j]));
      if ((splice_qpos = segmenti_positions[i]) < segmentj_positions[j]) {
	i++;

      } else if (splice_qpos > segmentj_positions[j]) {
	j++;

      } else {
	debug1(printf("splice matches at %d\n",splice_qpos));
	while (segmenti_nmismatches <= nmismatches_left && mismatch_positions_left[segmenti_nmismatches] < splice_qpos) {
	  segmenti_nmismatches++;
	}
	while (segmentj_nmismatches - 1 >= 0 && mismatch_positions_right[segmentj_nmismatches - 1] < splice_qpos) {
	  segmentj_nmismatches--;
	}

#if 0
	/* supporti = splice_qpos - pos5; */
	/* supportj = pos3 - splice_qpos; */
	debug1(printf("Considering candidate splice_qpos %d with supporti %d and %d mismatches, supportj %d and %d mismatches =>",
		      splice_qpos,supporti,segmenti_nmismatches,supportj,segmentj_nmismatches));
	if (supporti - 4*segmenti_nmismatches <= 0) {
	  debug1(printf(" no\n"));
	} else if (supportj - 4*segmentj_nmismatches <= 0) {
	  debug1(printf(" no\n"));
	} else {
	  debug1(printf(" yes\n"));
	  candidates = Intlist_push(candidates,splice_qpos);
	}
#endif

	debug1(printf("Evaluating known plus splice pos %d\n",splice_qpos));
	debug1(printf("%d mismatches on segmenti (%d..%d)\n",segmenti_nmismatches,pos5,splice_qpos));
	debug1(printf("%d mismatches on segmentj (%d..%d)\n",segmentj_nmismatches,splice_qpos,pos3));

	if (segmenti_knowni[i] >= 0) {
	  acceptor_prob = 1.0;
	} else {
	  acceptor_prob = Maxent_hr_antiacceptor_prob(segmenti_left + segmenti_positions[i],chroffset);
	}
	if (segmentj_knowni[j] >= 0) {
	  donor_prob = 1.0;
	} else {
	  donor_prob = Maxent_hr_antidonor_prob(segmentj_left + segmentj_positions[j],chroffset);
	}

	if (0 && salvagep == false && (donor_prob < MIN_PROB || acceptor_prob < MIN_PROB)) {
	  /* Skip */
	} else if ((nmismatches = segmenti_nmismatches + segmentj_nmismatches) < best_nmismatches) {
	  best_nmismatches = nmismatches;
	  best_splice_qpos = splice_qpos;
	  *best_nmismatches_i = *best_ref_nmismatches_i = segmenti_nmismatches;
	  *best_nmismatches_j = *best_ref_nmismatches_j = segmentj_nmismatches;
	  *best_donor_prob = donor_prob;
	  *best_acceptor_prob = acceptor_prob;
	  best_prob = donor_prob + acceptor_prob;

	} else if (nmismatches == best_nmismatches) {
	  if (donor_prob + acceptor_prob > best_prob) {
	  best_splice_qpos = splice_qpos;
	    *best_nmismatches_i = *best_ref_nmismatches_i = segmenti_nmismatches;
	    *best_nmismatches_j = *best_ref_nmismatches_j = segmentj_nmismatches;
	    *best_donor_prob = donor_prob;
	    *best_acceptor_prob = acceptor_prob;
	    best_prob = donor_prob + acceptor_prob;
	  }
	}
	i++; j++;
      }
    }
  }

  *best_nindels = 0;
  *best_indel_pos = -1;

  if (best_splice_qpos < 0) {
    /* Try with an indel */
    best_splice_qpos = spliceindel_resolve(&(*best_nindels),&(*best_indel_pos),
					   &(*best_nmismatches_i),&(*best_nmismatches_j),&(*best_nmismatches_indel),
					   &(*best_ref_nmismatches_i),&(*best_ref_nmismatches_j),
					   &(*best_ref_nmismatches_indel),&(*best_donor_prob),&(*best_acceptor_prob),
					   
					   univdiagonal_i,univdiagonal_j,
					   query_compress,plusp,chroffset,chrhigh,
					   
					   mismatch_positions_left,nmismatches_left,
					   mismatch_positions_right,nmismatches_right,
					   
					   segmenti_nsites,segmentj_nsites,
					   segmenti_positions,segmentj_positions,
					   segmenti_knowni,segmentj_knowni,

					   pos5,pos3,querylength,indelinfo,
					   sense_forward_p,genestrand,
					   /*nmismatches_allowed*/1,max_insertionlen,max_deletionlen);
  }

  if (best_splice_qpos >= 0) {
#if 0
    lefti = 0;
    while (lefti < nmismatches_left && mismatch_positions_left[lefti] < best_splice_qpos) {
      lefti++;
    }
    *best_nmismatches_i = *best_ref_nmismatches_i = lefti;
    
    righti = 0;
    while (righti < nmismatches_right && mismatch_positions_right[righti] >= best_splice_qpos) {
      righti++;
    }
    *best_nmismatches_j = *best_ref_nmismatches_j = righti;
#endif

    if (plusp == sense_forward_p) {
      best_probi = *best_donor_prob;
      best_probj = *best_acceptor_prob;
    } else {
      best_probi = *best_acceptor_prob;
      best_probj = *best_donor_prob;
    }

    supporti = best_splice_qpos - pos5;
    supportj = pos3 - best_splice_qpos;
    adj_supporti = supporti - 4*(*best_nmismatches_i);
    adj_supportj = supportj - 4*(*best_nmismatches_j);

    /* For local splicing, we check support before probability */
    if (supporti >= 25 && supportj >= 25 && (*best_nmismatches_i) + (*best_nmismatches_j) <= 1) {
      debug1(printf("Accepting splice pos %d, nindels %d, indel pos %d with supporti %d, mismatches %d, probi %f and supportj %d, mismatches %d, probj %f, based on support\n",
		    best_splice_qpos,*best_nindels,*best_indel_pos,supporti,*best_nmismatches_i,best_probi,
		    supportj,*best_nmismatches_j,best_probj));
      return best_splice_qpos;

    } else if (check_support_p == true && sufficient_support_p(adj_supporti,best_probi) == false) {
      debug1(printf("Rejecting splice pos %d, nindels %d, indel pos %d with supporti %d, mismatches %d, probi %f and supportj %d, mismatches %d, probj %f, based on adj support and prob\n",
		    best_splice_qpos,*best_nindels,*best_indel_pos,supporti,*best_nmismatches_i,best_probi,
		    supportj,*best_nmismatches_j,best_probj));
      /* Fall through */

    } else if (check_support_p == true && sufficient_support_p(adj_supportj,best_probj) == false) {
      debug1(printf("Rejecting splice pos %d, nindels %d, indel pos %d with supporti %d, mismatches %d, probi %f and supportj %d, mismatches %d, probj %f, based on adj support and prob\n",
		    best_splice_qpos,*best_nindels,*best_indel_pos,supporti,*best_nmismatches_i,best_probi,
		    supportj,*best_nmismatches_j,best_probj));
      /* Fall through */

    } else if (best_probi < SPLICE_PROB_LOW && best_probj < SPLICE_PROB_LOW) {
      debug1(printf("Rejecting splice pos %d, nindels %d, indel pos %d with supporti %d, mismatches %d, probi %f and supportj %d, mismatches %d, probj %f, based on probs\n",
		    best_splice_qpos,*best_nindels,*best_indel_pos,supporti,*best_nmismatches_i,best_probi,
		    supportj,*best_nmismatches_j,best_probj));
      /* Fall through */

    } else {
      debug1(printf("Accepting splice pos %d, nindels %d, indel pos %d with supporti %d, mismatches %d, probi %f and supportj %d, mismatches %d, probj %f\n",
		    best_splice_qpos,*best_nindels,*best_indel_pos,supporti,*best_nmismatches_i,best_probi,
		    supportj,*best_nmismatches_j,best_probj));
      return best_splice_qpos;
    }
  }

  if (salvagep == false) {
    *best_nmismatches_i = *best_nmismatches_j = -1; /* Indicates that calling procedure needs to compute numbers of mismatches  */
    return -1;
    
  } else {
    /* If we resort to atypical splice, then need to clear indel information */
    debug1(printf("Resorting to atypical splice\n"));

    *best_nindels = 0;
    *best_indel_pos = -1;
    return atypical_splice(&(*best_nmismatches_i),&(*best_nmismatches_j),
			   &(*best_ref_nmismatches_i),&(*best_ref_nmismatches_j),
			   &(*best_donor_prob),&(*best_acceptor_prob),
			   univdiagonal_i,univdiagonal_j,plusp,chroffset,
			   pos5,pos3,querylength,spliceinfo,nmismatches_left,nmismatches_right,
			   sense_forward_p,/*nmismatches_allowed*/1);
  }
}


static void
invert_positions (int *positions, int n, int querylength) {
  int i, j;
  int temp;

  for (i = 0, j = n - 1; i < n/2; i++, j--) {
    temp = querylength - positions[i];
    positions[i] = querylength - positions[j];
    positions[j] = temp;
  }
  if (i == j) {
    positions[i] = querylength - positions[i];
  }

  return;
}


void
donor_dinucleotide (char *donor1, char *donor2, Univcoord_T left, int splice_querypos, int querylength,
		    bool plusp, bool sense_forward_p) {
  char donor1_alt, donor2_alt;

  if (plusp == sense_forward_p) {
    if (plusp == true) {
      *donor1 = Genome_get_char(&donor1_alt,left + splice_querypos);
      *donor2 = Genome_get_char(&donor2_alt,left + splice_querypos + 1);
    } else {
      *donor1 = Genome_get_char(&donor1_alt,left + (querylength - splice_querypos));
      *donor2 = Genome_get_char(&donor2_alt,left + (querylength - splice_querypos) + 1);
    }

  } else {
    if (plusp == true) {
      *donor1 = complCode[(int) Genome_get_char(&donor1_alt,left + splice_querypos - 1)];
      *donor2 = complCode[(int) Genome_get_char(&donor2_alt,left + splice_querypos - 2)];
    } else {
      *donor1 = complCode[(int) Genome_get_char(&donor1_alt,left + (querylength - splice_querypos) - 1)];
      *donor2 = complCode[(int) Genome_get_char(&donor2_alt,left + (querylength - splice_querypos) - 2)];
    }
  }

  return;
}

void
acceptor_dinucleotide (char *acceptor1, char *acceptor2, Univcoord_T left, int splice_querypos, int querylength,
		       bool plusp, bool sense_forward_p) {
  char acceptor1_alt, acceptor2_alt;

  if (plusp == sense_forward_p) {
    if (plusp == true) {
      *acceptor1 = Genome_get_char(&acceptor1_alt,left + splice_querypos - 1);
      *acceptor2 = Genome_get_char(&acceptor2_alt,left + splice_querypos - 2);
    } else {
      *acceptor1 = Genome_get_char(&acceptor1_alt,left + (querylength - splice_querypos) - 1);
      *acceptor2 = Genome_get_char(&acceptor2_alt,left + (querylength - splice_querypos) - 2);
    }

  } else {
    if (plusp == true) {
      *acceptor1 = complCode[(int) Genome_get_char(&acceptor1_alt,left + splice_querypos)];
      *acceptor2 = complCode[(int) Genome_get_char(&acceptor2_alt,left + splice_querypos + 1)];
    } else {
      *acceptor1 = complCode[(int) Genome_get_char(&acceptor1_alt,left + (querylength - splice_querypos))];
      *acceptor2 = complCode[(int) Genome_get_char(&acceptor2_alt,left + (querylength - splice_querypos) + 1)];
    }
  }

  return;
}


int
Splice_resolve_fusion (char *donor1, char *donor2, char *acceptor1, char *acceptor2,
		       int *best_nindels, int *best_indel_pos,
		       int *best_nmismatches_5, int *best_nmismatches_3,

		       int *best_ref_nmismatches_5, int *best_ref_nmismatches_3,
		       double *best_donor_prob, double *best_acceptor_prob,
		       
		       Univcoord_T univdiagonal5, Univcoord_T univdiagonal3,
		       Compress_T query_compress_5, bool plusp_5, Univcoord_T chroffset5,
		       Compress_T query_compress_3, bool plusp_3, Univcoord_T chroffset3,
		     
		       int querypos5, int querypos3, int querylength,
		       Indelinfo_T indelinfo, Spliceinfo_T spliceinfo, Knownsplicing_T knownsplicing,
		       bool sense_forward_p, int genestrand,
		       int nmismatches_allowed, int max_insertionlen, int max_deletionlen) {

  int splice_querypos_low, splice_querypos_high;
  int *mismatch_positions_left, *mismatch_positions_right;
  int nmismatches_left, nmismatches_right;
  int mismatch5_adj, mismatch3_adj;
  
  int best_splice_querypos, splice_querypos, i, j;
  Univcoord_T *endpoints;
  uint64_t low_rank, high_rank, next_rank, rank;

  int best_nmismatches, nmismatches, segment5_nmismatches, segment3_nmismatches;
  double best_prob, best_prob5, best_prob3, donor_prob, acceptor_prob;

  int segment5_nsites, segment3_nsites;
  int *segment5_positions, *segment3_positions;
  int *segment5_knowni, *segment3_knowni;

  int adj_support5, adj_support3, support5, support3;
  Univcoord_T segment5_left, segment3_left;
  

#ifdef DEBUG2
  char *gbuffer1, *gbuffer2;
  static int ncalls = 0;
#endif


#ifdef DEBUG2
  segment5_left = univdiagonal5 - querylength;
  segment3_left = univdiagonal3 - querylength;

  printf("Splice_resolve_fusion, plusp %d and %d, sense_forward_p %d, call %d: Getting genome at segment5_left %u [%u] and segment3_left %u [%u], range %d..%d, querylength %d\n",
	 plusp_5,plusp_3,sense_forward_p,++ncalls,
	 segment5_left,segment5_left - chroffset5,segment3_left,segment3_left - chroffset3,
	 querypos5,querypos3,querylength);

#endif

  assert(Compress_fwdp(query_compress_5) == plusp_5);
  assert(Compress_fwdp(query_compress_3) == plusp_3);


#if 0
  /* TRIM QUERY AT CHROMOSOME BOUNDS */
  univdiagonal5 = segment5_left + (Univcoord_T) querylength;
  univdiagonal3 = segment3_left + (Univcoord_T) querylength;
  if (plusp_5 == true) {
    pos5 = querypos5;
  } else {
    pos5 = querylength - querypos5;
  }
  if (plusp_3 == true) {
    pos3 = querypos3;
  } else {
    pos3 = querylength - querypos3;
  }
  pos5 = (univdiagonal5 + pos5 >= chroffset5 + querylength) ? pos5 : (int) (chroffset5 - segment5_left);
  pos3 = (univdiagonal3 + pos3 <= chrhigh3 + querylength) ? pos3 : (int) (chrhigh3 - segment3_left);
#endif

  /* Determine feasibility of a splice */
  mismatch_positions_left = spliceinfo->mismatch_positions_left; /* Use allocated memory */

  /* Don't use nmismatches_allowed, because we want to count all mismatches for proper accounting and decision-making */
  if (plusp_5 == true) {
    debug2(printf("nmismatches_allowed is %d.  Calling Genomebits_mismatches_fromleft over %d..%d\n",
		  nmismatches_allowed,querypos5,querypos3));
    nmismatches_left = Genomebits_mismatches_fromleft(mismatch_positions_left,/*nmismatches_allowed*/querylength,
						      /*ome*/genomebits,/*ome_alt*/genomebits_alt,
						      query_compress_5,univdiagonal5,querylength,
						      querypos5,querypos3,/*plusp*/true,genestrand);
    mismatch5_adj = 0;				  /* splice occurs to right of querypos */
  } else {
    debug2(printf("nmismatches_allowed is %d.  Calling Genomebits_mismatches_fromleft over %d..%d\n",
		  nmismatches_allowed,querylength - querypos3,querylength - querypos5));
    nmismatches_left = Genomebits_mismatches_fromleft(mismatch_positions_left,/*nmismatches_allowed*/querylength,
						      /*ome*/genomebits,/*ome_alt*/genomebits_alt,
						      query_compress_5,univdiagonal5,querylength,
						      querylength - querypos3,querylength - querypos5,
						      /*plusp*/false,genestrand);
    invert_positions(mismatch_positions_left,nmismatches_left,querylength);
    mismatch_positions_left[nmismatches_left] = querypos3; /* invert_positions does not handle the last value */
    mismatch5_adj = 1;		/* splice occurs to left of querypos */
  }

  debug2(
	 printf("(4) %d mismatches on left from %d to %d at:",nmismatches_left,querypos5,querypos3);
	 for (i = 0; i <= nmismatches_left; i++) {
	   printf(" %d",mismatch_positions_left[i]);
	 }
	 printf("\n");
	 );

  mismatch_positions_right = spliceinfo->mismatch_positions_right; /* Use allocated memory */

  /* Don't use nmismatches_allowed, because we want to count all mismatches for proper accounting and decision-making */
  if (plusp_3 == true) {
    debug2(printf("nmismatches_allowed is %d.  Calling Genomebits_mismatches_fromright over %d..%d\n",
		  nmismatches_allowed,querypos5,querypos3));
    nmismatches_right = Genomebits_mismatches_fromright(mismatch_positions_right,/*nmismatches_allowed*/querylength,
							/*ome*/genomebits,/*ome_alt*/genomebits_alt,
							query_compress_3,univdiagonal3,querylength,
							querypos5,querypos3,/*plusp*/true,genestrand);
    mismatch3_adj = 0;				  /* splice occurs to right of querypos */
  } else {
    debug2(printf("nmismatches_allowed is %d.  Calling Genomebits_mismatches_fromright over %d..%d\n",
		  nmismatches_allowed,querylength - querypos3,querylength - querypos5));
    nmismatches_right = Genomebits_mismatches_fromright(mismatch_positions_right,/*nmismatches_allowed*/querylength,
							/*ome*/genomebits,/*ome_alt*/genomebits_alt,
							query_compress_3,univdiagonal3,querylength,
							querylength - querypos3,querylength - querypos5,
							/*plusp*/false,genestrand);
    invert_positions(mismatch_positions_right,nmismatches_right,querylength);
    mismatch_positions_right[nmismatches_right] = querypos5; /* invert_positions does not handle the last value */
    mismatch3_adj = 1;		/* splice occurs to left of querypos */
  }

  debug2(
	 printf("(4) %d mismatches on right from %d to %d at:",nmismatches_right,querypos3,querypos5);
	 for (i = 0; i <= nmismatches_right; i++) {
	   printf(" %d",mismatch_positions_right[i]);
	 }
	 printf("\n");
	 );

#ifdef DEBUG2
  gbuffer1 = (char *) CALLOC(querylength+1,sizeof(char));
  gbuffer2 = (char *) CALLOC(querylength+1,sizeof(char));
  Genome_fill_buffer(univdiagonal5 - querylength,querylength,gbuffer1);
  Genome_fill_buffer(univdiagonal3 - querylength,querylength,gbuffer2);
  if (plusp_3 != plusp_5) {
    make_complement_inplace(gbuffer2,querylength);
  }
    
  char *queryseq = Compress_queryseq(query_compress_5,querylength);

  printf("Splice_resolve_fusion, plusp %d and %d, nmismatches_allowed %d: Getting genome at left %llu and %llu\n",
	 plusp_5,plusp_3,nmismatches_allowed,(unsigned long long) segment5_left,(unsigned long long) segment3_left);
  printf("g1: %s\n",gbuffer1);
  printf("    ");
  print_diffs(gbuffer1,queryseq,querylength);
  printf("\n");
  printf("q:  %s\n",queryseq);
  printf("    ");
  print_diffs(gbuffer2,queryseq,querylength);
  printf("\n");
  printf("g2: %s\n",gbuffer2);
  FREE(gbuffer2);
  FREE(gbuffer1);
#endif


  /* Find low bound for splice pos based on nmismatches_right */
  /* Since we invert the positions, need to set the value above at [nmismatches_allowed] */
  if (nmismatches_right < nmismatches_allowed) {
    splice_querypos_low = mismatch_positions_right[nmismatches_right] - 1; /* ? need - 1 */
  } else {
    splice_querypos_low = mismatch_positions_right[nmismatches_allowed] - 1; /* ? need - 1 */
  }
  debug2(printf("  Splice low bound: %d",splice_querypos_low));
  if (splice_querypos_low < querypos5 + 1) {
    splice_querypos_low = querypos5 + 1;
    debug2(printf(" -- changed to %d\n",splice_querypos_low));
  }
  debug2(printf("\n"));

  /* Find high bound for splice pos based on nmismatches_left */
  if (nmismatches_left < nmismatches_allowed) {
    splice_querypos_high = mismatch_positions_left[nmismatches_left] + 1; /* ? need + 1 */;
  } else {
    splice_querypos_high = mismatch_positions_left[nmismatches_allowed] + 1; /* ? need + 1 */;
  }
  debug2(printf("  Splice high bound: %d",splice_querypos_high));
  if (splice_querypos_high > querypos3 - 1) {
    splice_querypos_high = querypos3 - 1;
    debug2(printf(" -- changed to %d\n",splice_querypos_high));
  }
  debug2(printf("\n"));

  if (splice_querypos_low >= splice_querypos_high) {
    /* The two ends cannot meet */
    *best_nmismatches_5 = *best_nmismatches_3 = -1; /* Indicates that calling procedure needs to compute numbers of mismatches  */
    return -1;
  }


/************************************************************************
 *   Known splicing
 ************************************************************************/

  segment5_left = univdiagonal5 - querylength;
  segment3_left = univdiagonal3 - querylength;

  best_splice_querypos = -1;
  if (sense_forward_p == true) {
    /* sense */
    segment5_nsites = segment3_nsites = 0;
    /* segment5_positions = spliceinfo->segment5_qpos_alloc; */
    /* segment3_positions = spliceinfo->segment3_qpos_alloc; */
    segment5_positions = spliceinfo->segmenti_knownpos;
    segment3_positions = spliceinfo->segmentj_knownpos;
    segment5_knowni = spliceinfo->segmenti_knowni;
    segment3_knowni = spliceinfo->segmentj_knowni;
    
    if (knownsplicing != NULL) {
      if (plusp_5 == sense_forward_p) {
	endpoints = Knownsplicing_donors(&low_rank,&high_rank,knownsplicing,
					 univdiagonal5,querylength,splice_querypos_low,splice_querypos_high);
      } else {
	endpoints = Knownsplicing_antidonors(&low_rank,&high_rank,knownsplicing,
					     univdiagonal5,querylength,querylength - splice_querypos_high,
					     querylength - splice_querypos_low);
      }
      debug2(printf("Knownsplicing donors at %u+%d..%d yields low_rank %lu to high_rank %lu\n",
		    segment5_left,splice_querypos_low,splice_querypos_high,low_rank,high_rank));
      /* Collapse duplicates because we don't care about partners */
      rank = low_rank;
      while (rank < high_rank) {
	debug4s(printf("Setting known donor %d for segment5 at %u..%u\n",(int) rank,endpoints[2*rank],endpoints[2*rank+1]));
	segment5_knowni[segment5_nsites] = (int) rank;
	segment5_positions[segment5_nsites] = endpoints[2*rank] - segment5_left;
	
	next_rank = rank + 1;
	while (next_rank < high_rank && endpoints[2*next_rank] == endpoints[2*rank]) {
	  next_rank += 1;
	}
	rank = next_rank;
      }
      
#ifdef DEBUG2
      printf("Found %d known donor5 sites:",segment5_nsites);
      for (i = 0; i < segment5_nsites; i++) {
	printf(" %d",segment5_positions[i]);
      }
      printf("\n");
#endif
      
      if (plusp_3 == sense_forward_p) {
	endpoints = Knownsplicing_acceptors(&low_rank,&high_rank,knownsplicing,
					    univdiagonal3,querylength,splice_querypos_low,splice_querypos_high);
      } else {
	endpoints = Knownsplicing_antiacceptors(&low_rank,&high_rank,knownsplicing,
						univdiagonal3,querylength,querylength - splice_querypos_high,
						querylength - splice_querypos_low);
      }
      debug2(printf("Knownsplicing acceptors at %u+%d..%d yields low_rank %lu to high_rank %lu\n",
		    segment3_left,splice_querypos_low,splice_querypos_high,low_rank,high_rank));
      /* Collapse duplicates because we don't care about partners */
      rank = low_rank;
      while (rank < high_rank) {
	debug4s(printf("Setting known acceptor %d for segment3 at %u..%u\n",(int) rank,endpoints[2*rank],endpoints[2*rank+1]));
	segment3_knowni[segment3_nsites] = (int) rank;
	segment3_positions[segment3_nsites++] = endpoints[2*rank] - segment3_left;
	
	next_rank = rank + 1;
	while (next_rank < high_rank && endpoints[2*next_rank] == endpoints[2*rank]) {
	  next_rank += 1;
	}
	rank = next_rank;
      }
#ifdef DEBUG2
      printf("Found %d known acceptor3 sites:",segment3_nsites);
      for (i = 0; i < segment3_nsites; i++) {
	printf(" %d",segment3_positions[i]);
      }
      printf("\n");
#endif
    }
    
    debug2(printf("  Splice low bound: %d\n",splice_querypos_low));
    debug2(printf("  Splice high bound: %d\n",splice_querypos_high));

    if (novelsplicingp == true) {
      if (plusp_5 == sense_forward_p) {
	debug2(printf("(1) CALLING Genome_donor_positions at %u on %d..%d\n",
		      segment5_left,splice_querypos_low,splice_querypos_high));
	segment5_positions[segment5_nsites] = querylength; /* Needed to terminate search in Genome_sites */
	segment5_nsites = Genome_donor_positions(segment5_positions = spliceinfo->segmenti_qpos_alloc,
						 segment5_knowni = spliceinfo->segmenti_knowni_alloc,
						 spliceinfo->segmenti_knownpos,
						 spliceinfo->segmenti_knowni,
						 segment5_left,splice_querypos_low,splice_querypos_high);
      } else {
	debug2(printf("(2) CALLING Genome_antidonor_positions at %u on %d..%d\n",
		      segment5_left,querylength - splice_querypos_high,querylength - splice_querypos_low));
	segment5_positions[segment5_nsites] = querylength;
	segment5_nsites = Genome_antidonor_positions(segment5_positions = spliceinfo->segmenti_qpos_alloc,
						     segment5_knowni = spliceinfo->segmenti_knowni_alloc,
						     spliceinfo->segmenti_knownpos,
						     spliceinfo->segmenti_knowni,
						     segment5_left,querylength - splice_querypos_high,
						     querylength - splice_querypos_low);
	invert_positions(segment5_positions,segment5_nsites,querylength);
      }
      
#ifdef DEBUG2
      printf("Found %d donor5 sites:",segment5_nsites);
      for (i = 0; i < segment5_nsites; i++) {
	printf(" %d",segment5_positions[i]);
	if (segment5_knowni[i] >= 0) {
	  printf(" [#%d]",segment5_knowni[i]);
	} else if (plusp_5 == sense_forward_p) {
	  printf(" (%.6f)",Maxent_hr_donor_prob(segment5_left + segment5_positions[i],chroffset5));
	} else {
	  printf(" (%.6f)",Maxent_hr_antidonor_prob(segment5_left + (querylength - segment5_positions[i]),chroffset5));
	}
      }
      printf("\n");
#endif
      
      if (plusp_3 == sense_forward_p) {
	debug2(printf("(3) CALLING Genome_acceptor_positions at %u on %d..%d\n",
		      segment3_left,splice_querypos_low,splice_querypos_high));
	segment3_positions[segment3_nsites] = querylength; /* Needed to terminate search in Genome_sites */
	segment3_nsites = Genome_acceptor_positions(segment3_positions = spliceinfo->segmentj_qpos_alloc,
						    segment3_knowni = spliceinfo->segmentj_knowni_alloc,
						    spliceinfo->segmentj_knownpos,
						    spliceinfo->segmentj_knowni,
						    segment3_left,splice_querypos_low,splice_querypos_high);
      } else {
	debug2(printf("(4) CALLING Genome_antiacceptor_positions at %u on %d..%d\n",
		      segment3_left,querylength - splice_querypos_high,querylength - splice_querypos_low));
	segment3_positions[segment3_nsites] = querylength; /* Needed to terminate search in Genome_sites */
	segment3_nsites = Genome_antiacceptor_positions(segment3_positions = spliceinfo->segmentj_qpos_alloc,
							segment3_knowni = spliceinfo->segmentj_knowni_alloc,
							spliceinfo->segmentj_knownpos,
							spliceinfo->segmentj_knowni,
							segment3_left,querylength - splice_querypos_high,
							querylength - splice_querypos_low);
	invert_positions(segment3_positions,segment3_nsites,querylength);
      }
      
#ifdef DEBUG2
      printf("Found %d acceptor3 sites:",segment3_nsites);
      for (i = 0; i < segment3_nsites; i++) {
	printf(" %d",segment3_positions[i]);
	if (segment3_knowni[i] >= 0) {
	  printf(" [#%d]",segment3_knowni[i]);
	} else if (plusp_3 == sense_forward_p) {
	  printf(" (%.6f)",Maxent_hr_acceptor_prob(segment3_left + segment3_positions[i],chroffset3));
	} else {
	  printf(" (%.6f)",Maxent_hr_antiacceptor_prob(segment3_left + (querylength - segment3_positions[i]),chroffset3));
	}
      }
      printf("\n");
#endif
    }

    
    if (segment5_nsites == 0 || segment3_nsites == 0) {
      debug2(printf("Splice sites are missing on one side, so returning -1\n"));
      *best_nmismatches_5 = *best_nmismatches_3 = -1; /* Indicates that calling procedure needs to compute numbers of mismatches  */
      return -1;
    } else {
      best_splice_querypos = -1;
      best_prob = 0.0;
      best_nmismatches = nmismatches_allowed + 1;
      *best_donor_prob = *best_acceptor_prob = 0.0;
    }
    
    /* Try for no indel */
    debug2(printf("Looking for splice only\n"));
    /* segment5_positions and segment3_positions are ascending */
    /* mismatch_positions_i are ascending, but mismatch_positions_right are descending */
    segment5_nmismatches = 0;
    segment3_nmismatches = nmismatches_right;
    i = j = 0;
    
    while (i < segment5_nsites && j < segment3_nsites) {
      debug2(printf("i [%d/%d]: %d and j [%d/%d]: %d\n",
		    i,segment5_nsites,segment5_positions[i],j,segment3_nsites,segment3_positions[j]));
      if ((splice_querypos = segment5_positions[i]) < segment3_positions[j]) {
	i++;
	
      } else if (splice_querypos > segment3_positions[j]) {
	j++;
	
      } else {
	debug2(printf("Evaluating splice querypos %d\n",splice_querypos));
	debug2(printf("Counting segment5_nmismatches from 0, stopping when value is < splice_querypos %d + adj %d\n",
		      splice_querypos,mismatch5_adj));
	while (segment5_nmismatches < nmismatches_left && mismatch_positions_left[segment5_nmismatches] < splice_querypos + mismatch5_adj) {
	  debug2a(printf("Saw segment5 mismatch at %d\n",mismatch_positions_left[segment5_nmismatches]));
	  segment5_nmismatches++;
	}
	debug2(printf("%d mismatches on segment5 (%d..%d)\n",segment5_nmismatches,querypos5,splice_querypos));

	debug2(printf("Counting segment5_nmismatches from %d, stopping when value is < splice_querypos %d + adj %d\n",
		      segment3_nmismatches,splice_querypos,mismatch3_adj));
	while (segment3_nmismatches - 1 >= 0 && mismatch_positions_right[segment3_nmismatches - 1] < splice_querypos + mismatch3_adj) {
	  debug2a(printf("Ignoring segment3 mismatch at %d\n",mismatch_positions_right[segment3_nmismatches - 1]));
	  segment3_nmismatches--;
	}
	debug2(printf("%d mismatches on segment3 (%d..%d)\n",segment3_nmismatches,splice_querypos,querypos3));

	
	if (segment5_knowni[i] >= 0) {
	  donor_prob = 1.0;
	} else if (plusp_5 == sense_forward_p) {
	  donor_prob = Maxent_hr_donor_prob(segment5_left + segment5_positions[i],chroffset5);
	} else {
	  donor_prob = Maxent_hr_antidonor_prob(segment5_left + (querylength - segment5_positions[i]),chroffset5);
	}
	if (segment3_knowni[j] >= 0) {
	  acceptor_prob = 1.0;
	} else if (plusp_3 == sense_forward_p) {
	  acceptor_prob = Maxent_hr_acceptor_prob(segment3_left + segment3_positions[j],chroffset3);
	} else {
	  acceptor_prob = Maxent_hr_antiacceptor_prob(segment3_left + (querylength - segment3_positions[j]),chroffset3);
	}

	if ((nmismatches = segment5_nmismatches + segment3_nmismatches) < best_nmismatches) {
	  best_nmismatches = nmismatches;
	  best_splice_querypos = splice_querypos;
	  *best_nmismatches_5 = *best_ref_nmismatches_5 = segment5_nmismatches;
	  *best_nmismatches_3 = *best_ref_nmismatches_3 = segment3_nmismatches;
	  *best_donor_prob = donor_prob;
	  *best_acceptor_prob = acceptor_prob;
	  donor_dinucleotide(&(*donor1),&(*donor2),segment5_left,splice_querypos,querylength,
			     plusp_5,sense_forward_p);
	  acceptor_dinucleotide(&(*acceptor1),&(*acceptor2),segment3_left,splice_querypos,querylength,
				plusp_3,sense_forward_p);
	  best_prob = donor_prob + acceptor_prob;
	  
	} else if (nmismatches == best_nmismatches) {
	  if (donor_prob + acceptor_prob > best_prob) {
	    best_splice_querypos = splice_querypos;
	    *best_nmismatches_5 = *best_ref_nmismatches_5 = segment5_nmismatches;
	    *best_nmismatches_3 = *best_ref_nmismatches_3 = segment3_nmismatches;
	    *best_donor_prob = donor_prob;
	    *best_acceptor_prob = acceptor_prob;
	    donor_dinucleotide(&(*donor1),&(*donor2),segment5_left,splice_querypos,querylength,
			       plusp_5,sense_forward_p);
	    acceptor_dinucleotide(&(*acceptor1),&(*acceptor2),segment3_left,splice_querypos,querylength,
				  plusp_3,sense_forward_p);
	    best_prob = donor_prob + acceptor_prob;
	  }
	}
	i++; j++;
      }
    }
    
  } else {
    /* antisense */
    segment5_nsites = segment3_nsites = 0;
    /* segment5_positions = spliceinfo->segment5_qpos_alloc; */
    /* segment3_positions = spliceinfo->segment3_qpos_alloc; */
    segment5_positions = spliceinfo->segmenti_knownpos;
    segment3_positions = spliceinfo->segmentj_knownpos;
    segment5_knowni = spliceinfo->segmenti_knowni;
    segment3_knowni = spliceinfo->segmentj_knowni;

    if (knownsplicing != NULL) {
      if (plusp_5 == sense_forward_p) {
	endpoints = Knownsplicing_acceptors(&low_rank,&high_rank,knownsplicing,
					    univdiagonal5,querylength,querylength - splice_querypos_high,
					    querylength - splice_querypos_low);
      } else {
	endpoints = Knownsplicing_antiacceptors(&low_rank,&high_rank,knownsplicing,
						univdiagonal5,querylength,splice_querypos_low,splice_querypos_high);
      }
      debug2(printf("Knownsplicing antiacceptors at %u+%d..%d yields low_rank %lu to high_rank %lu\n",
		    segment5_left,splice_querypos_low,splice_querypos_high,low_rank,high_rank));
      /* Collapse duplicates because we don't care about partners */
      rank = low_rank;
      while (rank < high_rank) {
	debug4s(printf("Setting known antiacceptor %d for segment5 at %u..%u\n",(int) rank,endpoints[2*rank],endpoints[2*rank+1]));
	segment5_knowni[segment5_nsites] = (int) rank;
	segment5_positions[segment5_nsites++] = endpoints[2*rank] - segment5_left;

	next_rank = rank + 1;
	while (next_rank < high_rank && endpoints[2*next_rank] == endpoints[2*rank]) {
	  next_rank += 1;
	}
	rank = next_rank;
      }
#ifdef DEBUG2
      printf("Found %d known acceptor5 sites:",segment5_nsites);
      for (i = 0; i < segment5_nsites; i++) {
	printf(" %d",segment5_positions[i]);
	printf("\n");
      }
#endif

      if (plusp_3 == sense_forward_p) {
	endpoints = Knownsplicing_donors(&low_rank,&high_rank,knownsplicing,
					 univdiagonal3,querylength,querylength - splice_querypos_high,
					 querylength - splice_querypos_low);
      } else {
	endpoints = Knownsplicing_antidonors(&low_rank,&high_rank,knownsplicing,
					     univdiagonal3,querylength,splice_querypos_low,splice_querypos_high);
      }
      debug2(printf("Knownsplicing antidonors at %u+%d..%d yields low_rank %lu to high_rank %lu\n",
		    segment3_left,splice_querypos_low,splice_querypos_high,low_rank,high_rank));
      /* Collapse duplicates because we don't care about partners */
      rank = low_rank;
      while (rank < high_rank) {
	debug4s(printf("Setting known antidonor %d for segment3 at %u..%u\n",(int) rank,endpoints[2*rank],endpoints[2*rank+1]));
	segment3_knowni[segment3_nsites] = (int) rank;
	segment3_positions[segment3_nsites++] = endpoints[2*rank] - segment3_left;

	next_rank = rank + 1;
	while (next_rank < high_rank && endpoints[2*next_rank] == endpoints[2*rank]) {
	  next_rank += 1;
	}
	rank = next_rank;
      }

#ifdef DEBUG2
      printf("Found %d known donor3 sites:",segment3_nsites);
      for (i = 0; i < segment3_nsites; i++) {
	printf(" %d",segment3_positions[i]);
      }
      printf("\n");
#endif

    }

    if (novelsplicingp == true) {
      if (plusp_5 == sense_forward_p) {
	debug2(printf("(5) CALLING Genome_acceptor_positions at %u on %d..%d\n",
		      segment5_left,querylength - splice_querypos_high,querylength - splice_querypos_low));
	segment5_positions[segment5_nsites] = querylength; /* Needed to terminate search in Genome_sites */
	segment5_nsites = Genome_acceptor_positions(segment5_positions = spliceinfo->segmenti_qpos_alloc,
						    segment5_knowni = spliceinfo->segmenti_knowni_alloc,
						    spliceinfo->segmenti_knownpos,
						    spliceinfo->segmenti_knowni,
						    segment5_left,querylength - splice_querypos_high,
						    querylength - splice_querypos_low);
	invert_positions(segment5_positions,segment5_nsites,querylength);
      } else {
	debug2(printf("(6) CALLING Genome_antiacceptor_positions at %u on %d..%d\n",
		      segment5_left,splice_querypos_low,splice_querypos_high));
	segment5_positions[segment5_nsites] = querylength; /* Needed to terminate search in Genome_sites */
	segment5_nsites = Genome_antiacceptor_positions(segment5_positions = spliceinfo->segmenti_qpos_alloc,
							segment5_knowni = spliceinfo->segmenti_knowni_alloc,
							spliceinfo->segmenti_knownpos,
							spliceinfo->segmenti_knowni,
							segment5_left,splice_querypos_low,splice_querypos_high);
      }

#ifdef DEBUG2
      printf("Found %d acceptor5 sites:",segment5_nsites);
      for (i = 0; i < segment5_nsites; i++) {
	printf(" %d",segment5_positions[i]);
	if (segment5_knowni[i] >= 0) {
	  printf(" [#%d]",segment5_knowni[i]);
	} else if (plusp_5 == sense_forward_p) {
	  printf(" (%.6f)",Maxent_hr_acceptor_prob(segment5_left + (querylength - segment5_positions[i]),chroffset5));
	} else {
	  printf(" (%.6f)",Maxent_hr_antiacceptor_prob(segment5_left + segment5_positions[i],chroffset5));
	}
      }
      printf("\n");
#endif

      if (plusp_3 == sense_forward_p) {
	debug2(printf("(7) CALLING Genome_donor_positions at %u on %d..%d\n",
		      segment3_left,querylength - splice_querypos_high,querylength - splice_querypos_low));
	segment3_positions[segment3_nsites] = querylength; /* Needed to terminate search in Genome_sites */
	segment3_nsites = Genome_donor_positions(segment3_positions = spliceinfo->segmentj_qpos_alloc,
						 segment3_knowni = spliceinfo->segmentj_knowni_alloc,
						 spliceinfo->segmentj_knownpos,
						 spliceinfo->segmentj_knowni,
						 segment3_left,querylength - splice_querypos_high,
						 querylength - splice_querypos_low);
	invert_positions(segment3_positions,segment3_nsites,querylength);
      } else {
	debug2(printf("(8) CALLING Genome_antidonor_positions at %u on %d..%d\n",
		      segment3_left,splice_querypos_low,splice_querypos_high));
	segment3_positions[segment3_nsites] = querylength; /* Needed to terminate search in Genome_sites */
	segment3_nsites = Genome_antidonor_positions(segment3_positions = spliceinfo->segmentj_qpos_alloc,
						     segment3_knowni = spliceinfo->segmentj_knowni_alloc,
						     spliceinfo->segmentj_knownpos,
						     spliceinfo->segmentj_knowni,
						     segment3_left,splice_querypos_low,splice_querypos_high);
      }

#ifdef DEBUG2
      printf("Found %d donor3 sites:",segment3_nsites);
      for (i = 0; i < segment3_nsites; i++) {
	printf(" %d",segment3_positions[i]);
	if (segment3_knowni[i] >= 0) {
	  printf(" [#%d]",segment3_knowni[i]);
	} else if (plusp_3 == sense_forward_p) {
	  printf(" (%.6f)",Maxent_hr_donor_prob(segment3_left + (querylength - segment3_positions[i]),chroffset3));
	} else {
	  printf(" (%.6f)",Maxent_hr_antidonor_prob(segment3_left + segment3_positions[i],chroffset3));
	}
      }
      printf("\n");
#endif
    }


    if (segment5_nsites == 0 || segment3_nsites == 0) {
      debug2(printf("Splice sites are missing on one side, so returning -1\n"));
      *best_nmismatches_5 = *best_nmismatches_3 = -1; /* Indicates that calling procedure needs to compute numbers of mismatches  */
      return -1;
    } else {
      best_splice_querypos = -1;
      best_prob = 0.0;
      best_nmismatches = nmismatches_allowed + 1;
      *best_donor_prob = *best_acceptor_prob = 0.0;
    }

    /* Try for no indel */
    debug2(printf("Looking for splice only\n"));
    /* segment5_positions and segment3_positions are ascending */
    /* mismatch_positions_i are ascending, but mismatch_positions_right are descending */
    segment5_nmismatches = 0;
    segment3_nmismatches = nmismatches_right;
    i = j = 0;

    while (i < segment5_nsites && j < segment3_nsites) {
      debug2(printf("i [%d/%d]: %d and j [%d/%d]: %d\n",
		    i,segment5_nsites,segment5_positions[i],j,segment3_nsites,segment3_positions[j]));
      if ((splice_querypos = segment5_positions[i]) < segment3_positions[j]) {
	i++;

      } else if (splice_querypos > segment3_positions[j]) {
	j++;

      } else {
	debug2(printf("Evaluating splice querypos %d\n",splice_querypos));
	debug2(printf("Counting segment5_nmismatches from 0, stopping when value is < splice_querypos %d + adj %d\n",
		      splice_querypos,mismatch5_adj));
	while (segment5_nmismatches < nmismatches_left && mismatch_positions_left[segment5_nmismatches] < splice_querypos + mismatch5_adj) {
	  debug2a(printf("Saw segment5 mismatch at %d\n",mismatch_positions_left[segment5_nmismatches]));
	  segment5_nmismatches++;
	}
	debug2(printf("%d mismatches on segment5 (%d..%d)\n",segment5_nmismatches,querypos5,splice_querypos));

	debug2(printf("Counting segment5_nmismatches from %d, stopping when value is < splice_querypos %d + adj %d\n",
		      segment3_nmismatches,splice_querypos,mismatch3_adj));
	while (segment3_nmismatches - 1 >= 0 && mismatch_positions_right[segment3_nmismatches - 1] < splice_querypos + mismatch3_adj) {
	  debug2a(printf("Ignoring segment3 mismatch at %d\n",mismatch_positions_right[segment3_nmismatches - 1]));
	  segment3_nmismatches--;
	}
	debug2(printf("%d mismatches on segment3 (%d..%d)\n",segment3_nmismatches,splice_querypos,querypos3));

	if (segment5_knowni[i] >= 0) {
	  acceptor_prob = 1.0;
	} else if (plusp_5 == sense_forward_p) {
	  acceptor_prob = Maxent_hr_acceptor_prob(segment5_left + (querylength - segment5_positions[i]),chroffset5);
	} else {
	  acceptor_prob = Maxent_hr_antiacceptor_prob(segment5_left + segment5_positions[i],chroffset5);
	}
	if (segment3_knowni[j] >= 0) {
	  donor_prob = 1.0;
	} else if (plusp_3 == sense_forward_p) {
	  donor_prob = Maxent_hr_donor_prob(segment3_left + (querylength - segment3_positions[j]),chroffset3);
	} else {
	  donor_prob = Maxent_hr_antidonor_prob(segment3_left + segment3_positions[j],chroffset3);
	}

	if ((nmismatches = segment5_nmismatches + segment3_nmismatches) < best_nmismatches) {
	  best_nmismatches = nmismatches;
	  best_splice_querypos = splice_querypos;
	  *best_nmismatches_5 = *best_ref_nmismatches_5 = segment5_nmismatches;
	  *best_nmismatches_3 = *best_ref_nmismatches_3 = segment3_nmismatches;
	  *best_donor_prob = donor_prob;
	  *best_acceptor_prob = acceptor_prob;
	  acceptor_dinucleotide(&(*acceptor1),&(*acceptor2),segment5_left,splice_querypos,querylength,
				plusp_5,sense_forward_p);
	  donor_dinucleotide(&(*donor1),&(*donor2),segment3_left,splice_querypos,querylength,
				plusp_3,sense_forward_p);
	  best_prob = donor_prob + acceptor_prob;

	} else if (nmismatches == best_nmismatches) {
	  if (donor_prob + acceptor_prob > best_prob) {
	  best_splice_querypos = splice_querypos;
	    *best_nmismatches_5 = *best_ref_nmismatches_5 = segment5_nmismatches;
	    *best_nmismatches_3 = *best_ref_nmismatches_3 = segment3_nmismatches;
	    *best_donor_prob = donor_prob;
	    *best_acceptor_prob = acceptor_prob;
	    acceptor_dinucleotide(&(*acceptor1),&(*acceptor2),segment5_left,splice_querypos,querylength,
				  plusp_5,sense_forward_p);
	    donor_dinucleotide(&(*donor1),&(*donor2),segment3_left,splice_querypos,querylength,
			       plusp_3,sense_forward_p);
	    best_prob = donor_prob + acceptor_prob;
	  }
	}
	i++; j++;
      }
    }
  }

  *best_nindels = 0;
  *best_indel_pos = -1;

  if (best_splice_querypos < 0) {
    /* TODO: Try with an indel */
#if 0
    best_splice_querypos =
      spliceindel_resolve_fusion(&(*best_nindels),&(*best_indel_pos),
				 &(*best_nmismatches_i),&(*best_nmismatches_j),&(*best_nmismatches_indel),
				 &(*best_ref_nmismatches_i),&(*best_ref_nmismatches_j),
				 &(*best_ref_nmismatches_indel),&(*best_donor_prob),&(*best_acceptor_prob),
					   
				 univdiagonal5,univdiagonal3,
				 query_compress_5,plusp_5,query_compress_3,plusp_3,
					   
				 mismatch_positions_left,nmismatches_left,
				 mismatch_positions_right,nmismatches_right,
					   
				 segment5_nsites,segment3_nsites,
				 segment5_positions,segment3_positions,
				 segment5_knowni,segment3_knowni,

				 pos5,pos3,querylength,indelinfo,
				 sense_forward_p,genestrand,
				 nmismatches_allowed,max_insertionlen,max_deletionlen);
#endif    
  }

  if (best_splice_querypos >= 0) {
#if 0
    lefti = 0;
    while (lefti < nmismatches_left && mismatch_positions_left[lefti] < best_splice_qpos) {
      lefti++;
    }
    *best_nmismatches_i = *best_ref_nmismatches_i = lefti;
    
    righti = 0;
    while (righti < nmismatches_right && mismatch_positions_right[righti] >= best_splice_qpos) {
      righti++;
    }
    *best_nmismatches_j = *best_ref_nmismatches_j = righti;
#endif

    if (sense_forward_p == true) {
      best_prob5 = *best_donor_prob;
      best_prob3 = *best_acceptor_prob;
    } else {
      best_prob5 = *best_acceptor_prob;
      best_prob3 = *best_donor_prob;
    }

    support5 = best_splice_querypos - querypos5;
    support3 = querypos3 - best_splice_querypos;

    adj_support5 = support5 - 4*(*best_nmismatches_5);
    adj_support3 = support3 - 4*(*best_nmismatches_3);

    /* For fusions, we check probability before support */
    if (best_prob5 < SPLICE_PROB_LOW || best_prob3 < SPLICE_PROB_LOW) {
      debug2(printf("Rejecting splice pos %d, nindels %d, indel pos %d with support5 %d, mismatches %d, prob5 %f and support3 %d, mismatches %d, prob3 %f, based on probs\n",
		    best_splice_querypos,*best_nindels,*best_indel_pos,support5,*best_nmismatches_5,best_prob5,
		    support3,*best_nmismatches_3,best_prob3));
      /* Fall through */

    } else if (support5 >= 25 && support3 >= 25 && (*best_nmismatches_5) + (*best_nmismatches_3) <= 1) {
      debug2(printf("Accepting splice pos %d, nindels %d, indel pos %d with support5 %d, mismatches %d, prob5 %f and support3 %d, mismatches %d, prob3 %f, based on support\n",
		    best_splice_querypos,*best_nindels,*best_indel_pos,support5,*best_nmismatches_5,best_prob5,
		    support3,*best_nmismatches_3,best_prob3));
      return best_splice_querypos;

    } else if (sufficient_support_p(adj_support5,best_prob5) == false) {
      debug2(printf("Rejecting splice pos %d, nindels %d, indel pos %d with support5 %d, mismatches %d, prob5 %f and support3 %d, mismatches %d, prob3 %f, based on adj support and prob\n",
		    best_splice_querypos,*best_nindels,*best_indel_pos,support5,*best_nmismatches_5,best_prob5,
		    support3,*best_nmismatches_3,best_prob3));
      /* Fall through */

    } else if (sufficient_support_p(adj_support3,best_prob3) == false) {
      debug2(printf("Rejecting splice pos %d, nindels %d, indel pos %d with support5 %d, mismatches %d, prob5 %f and support3 %d, mismatches %d, prob3 %f, based on adj support and prob\n",
		    best_splice_querypos,*best_nindels,*best_indel_pos,support5,*best_nmismatches_5,best_prob5,
		    support3,*best_nmismatches_3,best_prob3));
      /* Fall through */

    } else {
      debug2(printf("Accepting splice pos %d, nindels %d, indel pos %d with support5 %d, mismatches %d, prob5 %f and support3 %d, mismatches %d, prob3 %f\n",
		    best_splice_querypos,*best_nindels,*best_indel_pos,support5,*best_nmismatches_5,best_prob5,
		    support3,*best_nmismatches_3,best_prob3));
      return best_splice_querypos;
    }
  }

  /* If we resort to atypical splice, then need to clear indel information */
  /* Not allowing atypical splices for gene fusions */

  *best_nindels = 0;
  *best_indel_pos = -1;
  return -1;
}


