 /* file aldistsm_prot.c */

#if !defined(COMPILE_ENVIRONMENT)
#include <gp/stdcenvf.h> /* std compile environment for functions */
#endif


  int aldistsm_prot(ALIGNMENT_INT_PROT *aln_in, int (*w) (int,int,pcodeset*,int*),
      int return_alignment, double fom_threshold, ALIGNMENT_INT_PROT *aln_out,
      int *perr)
 /**********************************************************************/
 /*                                                                    */
 /*    Computes and returns the alignment distance between the symbols */
 /* in the two protected integer strings in *aln_in (nsa and nsb).     */
 /*    If <return_alignment> is T, this function returns as a          */
 /* by-product the particular alignment found, in *aln_out.  The two   */
 /* strings in *aln_out will have been put into alignment by inserting */
 /* nulls (zero) into one or both of them.                             */
 /*    This version considers splits and merges, recursively, using    */
 /* the value of "fom_threshold".  If a split or merge is found, an    */
 /* auxiliary symbol representing two or more pcode symbols is put     */
 /* into the aux table of aln_out.                                     */
 /*    W(i,j,) is a pointer to an integer cost (weight or distance)    */
 /* function of two integer variables and a pcodeset, which returns    */
 /* the distance from symbol i to j.                                   */
 /* w(i,j) is the cost of substituting int j for int i.                */
 /* w(0,j) is the cost of inserting int j;                             */
 /* w(i,0) is the cost of deleting int i;                              */
 /*                                                                    */
 /*   *perr = 0 means a.o.k.                                           */
 /*   error codes:                                                     */
 /*   11:invalid input parameters                                      */
 /*                                                                    */
 /**********************************************************************/
   {/* data: */
    char *proc = "aldistsm_prot";
    pcodeset *pcode1;
    short int d, dx;
    int smdel, sm_corr;
    boolean return_simple_alignment = T;
    boolean error_check = T;
    ALIGNMENT_INT_PROT *alnx;
    SM_TAB_STR2 smtabx, *smtab = &smtabx;
    /* used only if error checking is on: */
    ALIGNMENT_INT_PROT *aln_basic_bef, *aln_basic_aft;
/* code: */
 /**** start debug ****/
db_enter_msg(proc,0); /* debug only */
if (db_level > 0 )
   {printf("%s return_alignment = %s\n",pdb,bool_print(return_alignment));
    printf("%s the pcode is '%s'\n",pdb,(aln_in->pcset)->name);
    printf("%s na =%d, nb =%d\n",pdb,aln_in->nsa->str[0],aln_in->nsb->str[0]);
    printf("%s the input strings to align are:\n\n",pdb);
    dump_int_alignment_prot(aln_in);
   }
 /**** debug ****/

 /* initialize */
  *perr=0;
  d=0;
  pcode1 = aln_in->pcset;
  if (return_alignment) alnx = aln_out;
  else                  alnx = make_al_int_prot2("aldistsm_prot/alnx",pcode1);
  if (error_check)
    {aln_basic_bef = make_al_int_prot2("aldistsm_prot/aln_basic_bef",pcode1);
     aln_basic_aft = make_al_int_prot2("aldistsm_prot/aln_basic_aft",pcode1);
    }
/* start with a non-sm alignment: */
  d = aldist2_prot(aln_in,w,return_simple_alignment,alnx,perr);
/*  if (*perr > 0)  fprintf(stderr,"%s: aldist2_prot() returns err = %d\n",proc,*perr);*/
  if (*perr > 10) goto RETURN;

if (db_level > 0)
 {printf("%s simple alignment (aldist2) d=%d\n",pdb,d);
  printf("%s simple alignment (static)  d=%d\n",pdb,aldist_static_prot(alnx,perr));
/*  if (*perr > 0)  fprintf(stderr,"%s: aldist_static_prot() returns err = %d\n",proc,*perr);*/
  if (*perr > 10) goto RETURN;
  printf("%s simple phonetic alignment is:\n",pdb);
  dump_int_alignment4_prot(alnx);
 }

/* modify it to represent splits and merges: */
if (db_level > 0) printf("%s now modifying it to represent splits/merges.\n",pdb);
  smtab->nsaved = 0;
  smtab->nover  = 0;
  alnx->naux    = 0;
  sm_corr       = 0;
  if (error_check)
    {aln_basic_bef = copy_int_al_prot(aln_basic_bef,alnx);
    /* THIS DOESN'T MAKE SENSE: @@##??? */
     make_basic_int_al_prot(aln_basic_bef);
    }
  while ((smdel = sm_correction2_prot(alnx,fom_threshold,smtab,perr)) > 0)
    {sm_corr += smdel;
     sort_sm_by_iloc(smtab);
     put_sm_into_aln_prot(alnx,smtab,perr);
     if (error_check)
       {/* see if basic alnx was altered */
        aln_basic_aft = copy_int_al_prot(aln_basic_aft,alnx);
        make_basic_int_al_prot(aln_basic_aft);
        if ((!nstreq(aln_basic_bef->nsa->str,aln_basic_aft->nsa->str))
          ||(!nstreq(aln_basic_bef->nsb->str,aln_basic_aft->nsb->str)))         
          {printf("*WARNING:%s: sm procedure changed basic alignment.\n",proc);
           printf("Basic alignment before =\n");
           dump_int_alignment_prot(aln_basic_bef);
           printf("Basic alignment after =\n");
           dump_int_alignment_prot(aln_basic_aft);
          }
        aln_basic_bef = copy_int_al_prot(aln_basic_bef,aln_basic_aft);
       } /* end error check processing */
    }
  d -= sm_corr;

if (error_check)
  {/*** check is dynamically-calculated d = static d ***/
   dx = aldist_static_prot(alnx,perr);
   if (dx != d)
     {printf("*ERR:%s:sm1 sm_corr not correct.\n",proc);
      printf(" d=%d, dx(from aldist_static)=%d\n",d,dx);
  }  }

RETURN:

if (db_level > 0)
  {printf("%s at exit, alnx=\n",pdb);
   dump_int_alignment4_prot(alnx);
  }

  if (!return_alignment) free_al_int_prot(alnx);
  if (error_check)
    {free_al_int_prot(aln_basic_bef);
     free_al_int_prot(aln_basic_aft);
    }

 db_leave_msg(proc,0); /* debug only */

  return d;
  } /* end of function "aldistsm_prot()" */
 /* end of file "aldistsm_prot.c" */
