/* Do not edit this file, as it is generated by ./scripts/mksainseq.rb.
*/

static void gt_sain_PLAINSEQ_fast_induceLtypesuffixes1(GtSainseq *sainseq,
                                                 const GtUchar *plainseq,
                                         GtSsainindextype *suftab,
                                         GtUword nonspecialentries)
{
  GtUword lastupdatecc = 0;
  GtSsainindextype *suftabptr, *bucketptr = NULL;

  GtUsainindextype *fillptr = sainseq->bucketfillptr;

  gt_assert(sainseq->roundtable != NULL);
  for (suftabptr = suftab, sainseq->currentround = 0;
       suftabptr < suftab + nonspecialentries; suftabptr++)
  {
    GtSsainindextype position;
    if ((position = *suftabptr) > 0)
    {
      GtUword currentcc;

      if (position >= (GtSsainindextype) sainseq->totallength)
      {
        sainseq->currentround++;
        position -= (GtSsainindextype) sainseq->totallength;
      }
      currentcc = (GtUword)
plainseq[position];
      if (currentcc < sainseq->numofchars)
      {
        if (position > 0)
        {
          GtUword t, leftcontextcc;

          position--;
          leftcontextcc = (GtUword)
plainseq[position];
          t = (currentcc << 1) | (leftcontextcc < currentcc ? 1UL : 0);
          gt_assert(currentcc > 0 &&
                    sainseq->roundtable[t] <= sainseq->currentround);
          if (sainseq->roundtable[t] < sainseq->currentround)
          {
            position += (GtSsainindextype) sainseq->totallength;
            sainseq->roundtable[t] = sainseq->currentround;
          }
          GT_SAINUPDATEBUCKETPTR(currentcc);
          /* negative => position does not derive L-suffix
             positive => position may derive L-suffix */
          gt_assert(suftabptr < bucketptr);
          *bucketptr++ = (t & 1UL) ? ~position : position;
          *suftabptr = 0;
#ifdef SAINSHOWSTATE
          gt_assert(bucketptr != NULL);
          printf("L-induce: suftab[" GT_WU "]=" GT_WD "\n",
                  (GtUword) (bucketptr-1-suftab),*(bucketptr-1));
#endif
        }
      } else
      {
        *suftabptr = 0;
      }
    } else
    {
      if (position < 0)
      {
        *suftabptr = ~position;
      }
    }
  }
}

static void gt_sain_PLAINSEQ_induceLtypesuffixes1(GtSainseq *sainseq,
                                                 const GtUchar *plainseq,
                                         GtSsainindextype *suftab,
                                         GtUword nonspecialentries)
{
  GtUword lastupdatecc = 0;
  GtUsainindextype *fillptr = sainseq->bucketfillptr;

  GtSsainindextype *suftabptr, *bucketptr = NULL;

  gt_assert(sainseq->roundtable == NULL);
  for (suftabptr = suftab; suftabptr < suftab + nonspecialentries; suftabptr++)
  {
    GtSsainindextype position;
    if ((position = *suftabptr) > 0)
    {
      GtUword currentcc = (GtUword)
plainseq[position];
      if (currentcc < sainseq->numofchars)
      {
        if (position > 0)
        {
          GtUword leftcontextcc;

          position--;
          leftcontextcc = (GtUword)
plainseq[position];
          GT_SAINUPDATEBUCKETPTR(currentcc);
          /* negative => position does not derive L-suffix
             positive => position may derive L-suffix */
          gt_assert(suftabptr < bucketptr);
          *bucketptr++ = (leftcontextcc < currentcc) ? ~position : position;
          *suftabptr = 0;
#ifdef SAINSHOWSTATE
          gt_assert(bucketptr != NULL);
          printf("L-induce: suftab[" GT_WU "]=" GT_WD "\n",
                  (GtUword) (bucketptr-1-suftab),*(bucketptr-1));
#endif
        }
      } else
      {
        *suftabptr = 0;
      }
    } else
    {
      if (position < 0)
      {
        *suftabptr = ~position;
      }
    }
  }
}

static void gt_sain_PLAINSEQ_fast_induceStypesuffixes1(GtSainseq *sainseq,
                                                 const GtUchar *plainseq,
                                         GtSsainindextype *suftab,
                                         GtUword nonspecialentries)
{
  GtUword lastupdatecc = 0;
  GtUsainindextype *fillptr = sainseq->bucketfillptr;

  GtSsainindextype *suftabptr, *bucketptr = NULL;

  gt_assert(sainseq->roundtable != NULL);
  gt_sain_special_singleSinduction1(sainseq,
                                    suftab,
                                    (GtSsainindextype)
                                    (sainseq->totallength-1));
  if (sainseq->seqtype == GT_SAIN_ENCSEQ ||
      sainseq->seqtype == GT_SAIN_BARE_ENCSEQ)
  {
    gt_sain_induceStypes1fromspecialranges(sainseq,suftab);
  }
  for (suftabptr = suftab + nonspecialentries - 1; suftabptr >= suftab;
       suftabptr--)
  {
    GtSsainindextype position;
    if ((position = *suftabptr) > 0)
    {
      if (position >= (GtSsainindextype) sainseq->totallength)
      {
        sainseq->currentround++;
        position -= (GtSsainindextype) sainseq->totallength;
      }
      if (position > 0)
      {
        GtUword currentcc = (GtUword)
plainseq[position];
        if (currentcc < sainseq->numofchars)
        {
          GtUword t, leftcontextcc;

          position--;
          leftcontextcc = (GtUword)
plainseq[position];
          t = (currentcc << 1) | (leftcontextcc > currentcc ? 1UL : 0);
          gt_assert(sainseq->roundtable[t] <= sainseq->currentround);
          if (sainseq->roundtable[t] < sainseq->currentround)
          {
            position += (GtSsainindextype) sainseq->totallength;
            sainseq->roundtable[t] = sainseq->currentround;
          }
          GT_SAINUPDATEBUCKETPTR(currentcc);
          gt_assert(bucketptr != NULL && bucketptr - 1 < suftabptr);
          *(--bucketptr) = (t & 1UL) ? ~(position+1) : position;
#ifdef SAINSHOWSTATE
          printf("S-induce: suftab[" GT_WU "]=" GT_WD "\n",
                  (GtUword) (bucketptr - suftab),*bucketptr);
#endif
        }
      }
      *suftabptr = 0;
    }
  }
}

static void gt_sain_PLAINSEQ_induceStypesuffixes1(GtSainseq *sainseq,
                                                 const GtUchar *plainseq,
                                         GtSsainindextype *suftab,
                                         GtUword nonspecialentries)
{
  GtUword lastupdatecc = 0;
  GtUsainindextype *fillptr = sainseq->bucketfillptr;

  GtSsainindextype *suftabptr, *bucketptr = NULL;

  gt_assert(sainseq->roundtable == NULL);
  gt_sain_special_singleSinduction1(sainseq,
                                    suftab,
                                    (GtSsainindextype)
                                    (sainseq->totallength-1));
  if (sainseq->seqtype == GT_SAIN_ENCSEQ ||
      sainseq->seqtype == GT_SAIN_BARE_ENCSEQ)
  {
    gt_sain_induceStypes1fromspecialranges(sainseq,suftab);
  }
  for (suftabptr = suftab + nonspecialentries - 1; suftabptr >= suftab;
       suftabptr--)
  {
    GtSsainindextype position;
    if ((position = *suftabptr) > 0)
    {
      GtUword currentcc = (GtUword)
plainseq[position];
      if (currentcc < sainseq->numofchars)
      {
        GtUword leftcontextcc;

        position--;
        leftcontextcc = (GtUword)
plainseq[position];
        GT_SAINUPDATEBUCKETPTR(currentcc);
        gt_assert(bucketptr != NULL && bucketptr - 1 < suftabptr);
        *(--bucketptr) = (leftcontextcc > currentcc)
                          ? ~(position+1) : position;
#ifdef SAINSHOWSTATE
        printf("S-induce: suftab[" GT_WU "]=" GT_WD "\n",
               (GtUword) (bucketptr - suftab),*bucketptr);
#endif
      }
      *suftabptr = 0;
    }
  }
}

static void gt_sain_PLAINSEQ_induceLtypesuffixes2(const GtSainseq *sainseq,
                                                 const GtUchar *plainseq,
                                         GtSsainindextype *suftab,
                                         GtUword nonspecialentries)
{
  GtUword lastupdatecc = 0;
  GtUsainindextype *fillptr = sainseq->bucketfillptr;

  GtSsainindextype *suftabptr, *bucketptr = NULL;

  for (suftabptr = suftab; suftabptr < suftab + nonspecialentries; suftabptr++)
  {
    GtSsainindextype position = *suftabptr;
    *suftabptr = ~position;
    if (position > 0)
    {
      GtUword currentcc;

      position--;
      currentcc = (GtUword)
plainseq[position];
      if (currentcc < sainseq->numofchars)
      {
        gt_assert(currentcc > 0);
        GT_SAINUPDATEBUCKETPTR(currentcc);
        gt_assert(bucketptr != NULL && suftabptr < bucketptr);
        *bucketptr++ = (position > 0 &&
                        ((GtUword)
plainseq[position-1]) < currentcc)
                        ? ~position : position;
#ifdef SAINSHOWSTATE
        gt_assert(bucketptr != NULL);
        printf("L-induce: suftab[" GT_WU "]=" GT_WD "\n",
               (GtUword) (bucketptr-1-suftab),*(bucketptr-1));
#endif
      }
    }
  }
}

static void gt_sain_PLAINSEQ_induceStypesuffixes2(const GtSainseq *sainseq,
                                                 const GtUchar *plainseq,
                                         GtSsainindextype *suftab,
                                         GtUword nonspecialentries)
{
  GtUword lastupdatecc = 0;
  GtUsainindextype *fillptr = sainseq->bucketfillptr;

  GtSsainindextype *suftabptr, *bucketptr = NULL;

  gt_sain_special_singleSinduction2(sainseq,
                                    suftab,
                                    (GtSsainindextype) sainseq->totallength,
                                    nonspecialentries);
  if (sainseq->seqtype == GT_SAIN_ENCSEQ ||
      sainseq->seqtype == GT_SAIN_BARE_ENCSEQ)
  {
    gt_sain_induceStypes2fromspecialranges(sainseq,suftab,nonspecialentries);
  }
  for (suftabptr = suftab + nonspecialentries - 1; suftabptr >= suftab;
       suftabptr--)
  {
    GtSsainindextype position;
    if ((position = *suftabptr) > 0)
    {
      GtUword currentcc;

      position--;
      currentcc = (GtUword)
plainseq[position];
      if (currentcc < sainseq->numofchars)
      {
        GT_SAINUPDATEBUCKETPTR(currentcc);
        gt_assert(bucketptr != NULL && bucketptr - 1 < suftabptr);
        *(--bucketptr) = (position == 0 ||
                          ((GtUword)
plainseq[position-1]) > currentcc)
                         ? ~position : position;
#ifdef SAINSHOWSTATE
        gt_assert(bucketptr != NULL);
        printf("S-induce: suftab[" GT_WU "]=" GT_WD "\n",
                (GtUword) (bucketptr-suftab),*bucketptr);
#endif
      }
    } else
    {
      *suftabptr = ~position;
    }
  }
}

static void gt_sain_ENCSEQ_fast_induceLtypesuffixes1(GtSainseq *sainseq,
                                                 const GtEncseq *encseq,
                                         GtSsainindextype *suftab,
                                         GtUword nonspecialentries)
{
  GtUword lastupdatecc = 0;
  GtSsainindextype *suftabptr, *bucketptr = NULL;

  GtUsainindextype *fillptr = sainseq->bucketfillptr;

  gt_assert(sainseq->roundtable != NULL);
  for (suftabptr = suftab, sainseq->currentround = 0;
       suftabptr < suftab + nonspecialentries; suftabptr++)
  {
    GtSsainindextype position;
    if ((position = *suftabptr) > 0)
    {
      GtUword currentcc;

      if (position >= (GtSsainindextype) sainseq->totallength)
      {
        sainseq->currentround++;
        position -= (GtSsainindextype) sainseq->totallength;
      }
      currentcc = (GtUword) gt_encseq_get_encoded_char(
encseq,
(GtUword) (position),
sainseq->readmode);
      if (currentcc < sainseq->numofchars)
      {
        if (position > 0)
        {
          GtUword t, leftcontextcc;

          position--;
          leftcontextcc = (GtUword) gt_encseq_get_encoded_char(
encseq,
(GtUword) (position),
sainseq->readmode);
          t = (currentcc << 1) | (leftcontextcc < currentcc ? 1UL : 0);
          gt_assert(currentcc > 0 &&
                    sainseq->roundtable[t] <= sainseq->currentround);
          if (sainseq->roundtable[t] < sainseq->currentround)
          {
            position += (GtSsainindextype) sainseq->totallength;
            sainseq->roundtable[t] = sainseq->currentround;
          }
          GT_SAINUPDATEBUCKETPTR(currentcc);
          /* negative => position does not derive L-suffix
             positive => position may derive L-suffix */
          gt_assert(suftabptr < bucketptr);
          *bucketptr++ = (t & 1UL) ? ~position : position;
          *suftabptr = 0;
#ifdef SAINSHOWSTATE
          gt_assert(bucketptr != NULL);
          printf("L-induce: suftab[" GT_WU "]=" GT_WD "\n",
                  (GtUword) (bucketptr-1-suftab),*(bucketptr-1));
#endif
        }
      } else
      {
        *suftabptr = 0;
      }
    } else
    {
      if (position < 0)
      {
        *suftabptr = ~position;
      }
    }
  }
}

static void gt_sain_ENCSEQ_induceLtypesuffixes1(GtSainseq *sainseq,
                                                 const GtEncseq *encseq,
                                         GtSsainindextype *suftab,
                                         GtUword nonspecialentries)
{
  GtUword lastupdatecc = 0;
  GtUsainindextype *fillptr = sainseq->bucketfillptr;

  GtSsainindextype *suftabptr, *bucketptr = NULL;

  gt_assert(sainseq->roundtable == NULL);
  for (suftabptr = suftab; suftabptr < suftab + nonspecialentries; suftabptr++)
  {
    GtSsainindextype position;
    if ((position = *suftabptr) > 0)
    {
      GtUword currentcc = (GtUword) gt_encseq_get_encoded_char(
encseq,
(GtUword) (position),
sainseq->readmode);
      if (currentcc < sainseq->numofchars)
      {
        if (position > 0)
        {
          GtUword leftcontextcc;

          position--;
          leftcontextcc = (GtUword) gt_encseq_get_encoded_char(
encseq,
(GtUword) (position),
sainseq->readmode);
          GT_SAINUPDATEBUCKETPTR(currentcc);
          /* negative => position does not derive L-suffix
             positive => position may derive L-suffix */
          gt_assert(suftabptr < bucketptr);
          *bucketptr++ = (leftcontextcc < currentcc) ? ~position : position;
          *suftabptr = 0;
#ifdef SAINSHOWSTATE
          gt_assert(bucketptr != NULL);
          printf("L-induce: suftab[" GT_WU "]=" GT_WD "\n",
                  (GtUword) (bucketptr-1-suftab),*(bucketptr-1));
#endif
        }
      } else
      {
        *suftabptr = 0;
      }
    } else
    {
      if (position < 0)
      {
        *suftabptr = ~position;
      }
    }
  }
}

static void gt_sain_ENCSEQ_fast_induceStypesuffixes1(GtSainseq *sainseq,
                                                 const GtEncseq *encseq,
                                         GtSsainindextype *suftab,
                                         GtUword nonspecialentries)
{
  GtUword lastupdatecc = 0;
  GtUsainindextype *fillptr = sainseq->bucketfillptr;

  GtSsainindextype *suftabptr, *bucketptr = NULL;

  gt_assert(sainseq->roundtable != NULL);
  gt_sain_special_singleSinduction1(sainseq,
                                    suftab,
                                    (GtSsainindextype)
                                    (sainseq->totallength-1));
  if (sainseq->seqtype == GT_SAIN_ENCSEQ ||
      sainseq->seqtype == GT_SAIN_BARE_ENCSEQ)
  {
    gt_sain_induceStypes1fromspecialranges(sainseq,suftab);
  }
  for (suftabptr = suftab + nonspecialentries - 1; suftabptr >= suftab;
       suftabptr--)
  {
    GtSsainindextype position;
    if ((position = *suftabptr) > 0)
    {
      if (position >= (GtSsainindextype) sainseq->totallength)
      {
        sainseq->currentround++;
        position -= (GtSsainindextype) sainseq->totallength;
      }
      if (position > 0)
      {
        GtUword currentcc = (GtUword) gt_encseq_get_encoded_char(
encseq,
(GtUword) (position),
sainseq->readmode);
        if (currentcc < sainseq->numofchars)
        {
          GtUword t, leftcontextcc;

          position--;
          leftcontextcc = (GtUword) gt_encseq_get_encoded_char(
encseq,
(GtUword) (position),
sainseq->readmode);
          t = (currentcc << 1) | (leftcontextcc > currentcc ? 1UL : 0);
          gt_assert(sainseq->roundtable[t] <= sainseq->currentround);
          if (sainseq->roundtable[t] < sainseq->currentround)
          {
            position += (GtSsainindextype) sainseq->totallength;
            sainseq->roundtable[t] = sainseq->currentround;
          }
          GT_SAINUPDATEBUCKETPTR(currentcc);
          gt_assert(bucketptr != NULL && bucketptr - 1 < suftabptr);
          *(--bucketptr) = (t & 1UL) ? ~(position+1) : position;
#ifdef SAINSHOWSTATE
          printf("S-induce: suftab[" GT_WU "]=" GT_WD "\n",
                  (GtUword) (bucketptr - suftab),*bucketptr);
#endif
        }
      }
      *suftabptr = 0;
    }
  }
}

static void gt_sain_ENCSEQ_induceStypesuffixes1(GtSainseq *sainseq,
                                                 const GtEncseq *encseq,
                                         GtSsainindextype *suftab,
                                         GtUword nonspecialentries)
{
  GtUword lastupdatecc = 0;
  GtUsainindextype *fillptr = sainseq->bucketfillptr;

  GtSsainindextype *suftabptr, *bucketptr = NULL;

  gt_assert(sainseq->roundtable == NULL);
  gt_sain_special_singleSinduction1(sainseq,
                                    suftab,
                                    (GtSsainindextype)
                                    (sainseq->totallength-1));
  if (sainseq->seqtype == GT_SAIN_ENCSEQ ||
      sainseq->seqtype == GT_SAIN_BARE_ENCSEQ)
  {
    gt_sain_induceStypes1fromspecialranges(sainseq,suftab);
  }
  for (suftabptr = suftab + nonspecialentries - 1; suftabptr >= suftab;
       suftabptr--)
  {
    GtSsainindextype position;
    if ((position = *suftabptr) > 0)
    {
      GtUword currentcc = (GtUword) gt_encseq_get_encoded_char(
encseq,
(GtUword) (position),
sainseq->readmode);
      if (currentcc < sainseq->numofchars)
      {
        GtUword leftcontextcc;

        position--;
        leftcontextcc = (GtUword) gt_encseq_get_encoded_char(
encseq,
(GtUword) (position),
sainseq->readmode);
        GT_SAINUPDATEBUCKETPTR(currentcc);
        gt_assert(bucketptr != NULL && bucketptr - 1 < suftabptr);
        *(--bucketptr) = (leftcontextcc > currentcc)
                          ? ~(position+1) : position;
#ifdef SAINSHOWSTATE
        printf("S-induce: suftab[" GT_WU "]=" GT_WD "\n",
               (GtUword) (bucketptr - suftab),*bucketptr);
#endif
      }
      *suftabptr = 0;
    }
  }
}

static void gt_sain_ENCSEQ_induceLtypesuffixes2(const GtSainseq *sainseq,
                                                 const GtEncseq *encseq,
                                         GtSsainindextype *suftab,
                                         GtUword nonspecialentries)
{
  GtUword lastupdatecc = 0;
  GtUsainindextype *fillptr = sainseq->bucketfillptr;

  GtSsainindextype *suftabptr, *bucketptr = NULL;

  for (suftabptr = suftab; suftabptr < suftab + nonspecialentries; suftabptr++)
  {
    GtSsainindextype position = *suftabptr;
    *suftabptr = ~position;
    if (position > 0)
    {
      GtUword currentcc;

      position--;
      currentcc = (GtUword) gt_encseq_get_encoded_char(
encseq,
(GtUword) (position),
sainseq->readmode);
      if (currentcc < sainseq->numofchars)
      {
        gt_assert(currentcc > 0);
        GT_SAINUPDATEBUCKETPTR(currentcc);
        gt_assert(bucketptr != NULL && suftabptr < bucketptr);
        *bucketptr++ = (position > 0 &&
                        ((GtUword) gt_encseq_get_encoded_char(
encseq,
(GtUword) (position-1),
sainseq->readmode)) < currentcc)
                        ? ~position : position;
#ifdef SAINSHOWSTATE
        gt_assert(bucketptr != NULL);
        printf("L-induce: suftab[" GT_WU "]=" GT_WD "\n",
               (GtUword) (bucketptr-1-suftab),*(bucketptr-1));
#endif
      }
    }
  }
}

static void gt_sain_ENCSEQ_induceStypesuffixes2(const GtSainseq *sainseq,
                                                 const GtEncseq *encseq,
                                         GtSsainindextype *suftab,
                                         GtUword nonspecialentries)
{
  GtUword lastupdatecc = 0;
  GtUsainindextype *fillptr = sainseq->bucketfillptr;

  GtSsainindextype *suftabptr, *bucketptr = NULL;

  gt_sain_special_singleSinduction2(sainseq,
                                    suftab,
                                    (GtSsainindextype) sainseq->totallength,
                                    nonspecialentries);
  if (sainseq->seqtype == GT_SAIN_ENCSEQ ||
      sainseq->seqtype == GT_SAIN_BARE_ENCSEQ)
  {
    gt_sain_induceStypes2fromspecialranges(sainseq,suftab,nonspecialentries);
  }
  for (suftabptr = suftab + nonspecialentries - 1; suftabptr >= suftab;
       suftabptr--)
  {
    GtSsainindextype position;
    if ((position = *suftabptr) > 0)
    {
      GtUword currentcc;

      position--;
      currentcc = (GtUword) gt_encseq_get_encoded_char(
encseq,
(GtUword) (position),
sainseq->readmode);
      if (currentcc < sainseq->numofchars)
      {
        GT_SAINUPDATEBUCKETPTR(currentcc);
        gt_assert(bucketptr != NULL && bucketptr - 1 < suftabptr);
        *(--bucketptr) = (position == 0 ||
                          ((GtUword) gt_encseq_get_encoded_char(
encseq,
(GtUword) (position-1),
sainseq->readmode)) > currentcc)
                         ? ~position : position;
#ifdef SAINSHOWSTATE
        gt_assert(bucketptr != NULL);
        printf("S-induce: suftab[" GT_WU "]=" GT_WD "\n",
                (GtUword) (bucketptr-suftab),*bucketptr);
#endif
      }
    } else
    {
      *suftabptr = ~position;
    }
  }
}

static void gt_sain_INTSEQ_fast_induceLtypesuffixes1(GtSainseq *sainseq,
                                                 const GtUsainindextype *array,
                                         GtSsainindextype *suftab,
                                         GtUword nonspecialentries)
{
  GtUword lastupdatecc = 0;
  GtSsainindextype *suftabptr, *bucketptr = NULL;

  GtUsainindextype *fillptr = sainseq->bucketfillptr;

  gt_assert(sainseq->roundtable != NULL);
  for (suftabptr = suftab, sainseq->currentround = 0;
       suftabptr < suftab + nonspecialentries; suftabptr++)
  {
    GtSsainindextype position;
    if ((position = *suftabptr) > 0)
    {
      GtUword currentcc;

      if (position >= (GtSsainindextype) sainseq->totallength)
      {
        sainseq->currentround++;
        position -= (GtSsainindextype) sainseq->totallength;
      }
      currentcc = (GtUword) array[position];
      if (currentcc < sainseq->numofchars)
      {
        if (position > 0)
        {
          GtUword t, leftcontextcc;

          position--;
          leftcontextcc = (GtUword) array[position];
          t = (currentcc << 1) | (leftcontextcc < currentcc ? 1UL : 0);
          gt_assert(currentcc > 0 &&
                    sainseq->roundtable[t] <= sainseq->currentround);
          if (sainseq->roundtable[t] < sainseq->currentround)
          {
            position += (GtSsainindextype) sainseq->totallength;
            sainseq->roundtable[t] = sainseq->currentround;
          }
          GT_SAINUPDATEBUCKETPTR(currentcc);
          /* negative => position does not derive L-suffix
             positive => position may derive L-suffix */
          gt_assert(suftabptr < bucketptr);
          *bucketptr++ = (t & 1UL) ? ~position : position;
          *suftabptr = 0;
#ifdef SAINSHOWSTATE
          gt_assert(bucketptr != NULL);
          printf("L-induce: suftab[" GT_WU "]=" GT_WD "\n",
                  (GtUword) (bucketptr-1-suftab),*(bucketptr-1));
#endif
        }
      } else
      {
        *suftabptr = 0;
      }
    } else
    {
      if (position < 0)
      {
        *suftabptr = ~position;
      }
    }
  }
}

static void gt_sain_INTSEQ_induceLtypesuffixes1(GtSainseq *sainseq,
                                                 const GtUsainindextype *array,
                                         GtSsainindextype *suftab,
                                         GtUword nonspecialentries)
{
  GtUword lastupdatecc = 0;
  GtUsainindextype *fillptr = sainseq->bucketfillptr;

  GtSsainindextype *suftabptr, *bucketptr = NULL;

  gt_assert(sainseq->roundtable == NULL);
  for (suftabptr = suftab; suftabptr < suftab + nonspecialentries; suftabptr++)
  {
    GtSsainindextype position;
    if ((position = *suftabptr) > 0)
    {
      GtUword currentcc = (GtUword) array[position];
      if (currentcc < sainseq->numofchars)
      {
        if (position > 0)
        {
          GtUword leftcontextcc;

          position--;
          leftcontextcc = (GtUword) array[position];
          GT_SAINUPDATEBUCKETPTR(currentcc);
          /* negative => position does not derive L-suffix
             positive => position may derive L-suffix */
          gt_assert(suftabptr < bucketptr);
          *bucketptr++ = (leftcontextcc < currentcc) ? ~position : position;
          *suftabptr = 0;
#ifdef SAINSHOWSTATE
          gt_assert(bucketptr != NULL);
          printf("L-induce: suftab[" GT_WU "]=" GT_WD "\n",
                  (GtUword) (bucketptr-1-suftab),*(bucketptr-1));
#endif
        }
      } else
      {
        *suftabptr = 0;
      }
    } else
    {
      if (position < 0)
      {
        *suftabptr = ~position;
      }
    }
  }
}

static void gt_sain_INTSEQ_fast_induceStypesuffixes1(GtSainseq *sainseq,
                                                 const GtUsainindextype *array,
                                         GtSsainindextype *suftab,
                                         GtUword nonspecialentries)
{
  GtUword lastupdatecc = 0;
  GtUsainindextype *fillptr = sainseq->bucketfillptr;

  GtSsainindextype *suftabptr, *bucketptr = NULL;

  gt_assert(sainseq->roundtable != NULL);
  gt_sain_special_singleSinduction1(sainseq,
                                    suftab,
                                    (GtSsainindextype)
                                    (sainseq->totallength-1));
  if (sainseq->seqtype == GT_SAIN_ENCSEQ ||
      sainseq->seqtype == GT_SAIN_BARE_ENCSEQ)
  {
    gt_sain_induceStypes1fromspecialranges(sainseq,suftab);
  }
  for (suftabptr = suftab + nonspecialentries - 1; suftabptr >= suftab;
       suftabptr--)
  {
    GtSsainindextype position;
    if ((position = *suftabptr) > 0)
    {
      if (position >= (GtSsainindextype) sainseq->totallength)
      {
        sainseq->currentround++;
        position -= (GtSsainindextype) sainseq->totallength;
      }
      if (position > 0)
      {
        GtUword currentcc = (GtUword) array[position];
        if (currentcc < sainseq->numofchars)
        {
          GtUword t, leftcontextcc;

          position--;
          leftcontextcc = (GtUword) array[position];
          t = (currentcc << 1) | (leftcontextcc > currentcc ? 1UL : 0);
          gt_assert(sainseq->roundtable[t] <= sainseq->currentround);
          if (sainseq->roundtable[t] < sainseq->currentround)
          {
            position += (GtSsainindextype) sainseq->totallength;
            sainseq->roundtable[t] = sainseq->currentround;
          }
          GT_SAINUPDATEBUCKETPTR(currentcc);
          gt_assert(bucketptr != NULL && bucketptr - 1 < suftabptr);
          *(--bucketptr) = (t & 1UL) ? ~(position+1) : position;
#ifdef SAINSHOWSTATE
          printf("S-induce: suftab[" GT_WU "]=" GT_WD "\n",
                  (GtUword) (bucketptr - suftab),*bucketptr);
#endif
        }
      }
      *suftabptr = 0;
    }
  }
}

static void gt_sain_INTSEQ_induceStypesuffixes1(GtSainseq *sainseq,
                                                 const GtUsainindextype *array,
                                         GtSsainindextype *suftab,
                                         GtUword nonspecialentries)
{
  GtUword lastupdatecc = 0;
  GtUsainindextype *fillptr = sainseq->bucketfillptr;

  GtSsainindextype *suftabptr, *bucketptr = NULL;

  gt_assert(sainseq->roundtable == NULL);
  gt_sain_special_singleSinduction1(sainseq,
                                    suftab,
                                    (GtSsainindextype)
                                    (sainseq->totallength-1));
  if (sainseq->seqtype == GT_SAIN_ENCSEQ ||
      sainseq->seqtype == GT_SAIN_BARE_ENCSEQ)
  {
    gt_sain_induceStypes1fromspecialranges(sainseq,suftab);
  }
  for (suftabptr = suftab + nonspecialentries - 1; suftabptr >= suftab;
       suftabptr--)
  {
    GtSsainindextype position;
    if ((position = *suftabptr) > 0)
    {
      GtUword currentcc = (GtUword) array[position];
      if (currentcc < sainseq->numofchars)
      {
        GtUword leftcontextcc;

        position--;
        leftcontextcc = (GtUword) array[position];
        GT_SAINUPDATEBUCKETPTR(currentcc);
        gt_assert(bucketptr != NULL && bucketptr - 1 < suftabptr);
        *(--bucketptr) = (leftcontextcc > currentcc)
                          ? ~(position+1) : position;
#ifdef SAINSHOWSTATE
        printf("S-induce: suftab[" GT_WU "]=" GT_WD "\n",
               (GtUword) (bucketptr - suftab),*bucketptr);
#endif
      }
      *suftabptr = 0;
    }
  }
}

static void gt_sain_INTSEQ_induceLtypesuffixes2(const GtSainseq *sainseq,
                                                 const GtUsainindextype *array,
                                         GtSsainindextype *suftab,
                                         GtUword nonspecialentries)
{
  GtUword lastupdatecc = 0;
  GtUsainindextype *fillptr = sainseq->bucketfillptr;

  GtSsainindextype *suftabptr, *bucketptr = NULL;

  for (suftabptr = suftab; suftabptr < suftab + nonspecialentries; suftabptr++)
  {
    GtSsainindextype position = *suftabptr;
    *suftabptr = ~position;
    if (position > 0)
    {
      GtUword currentcc;

      position--;
      currentcc = (GtUword) array[position];
      if (currentcc < sainseq->numofchars)
      {
        gt_assert(currentcc > 0);
        GT_SAINUPDATEBUCKETPTR(currentcc);
        gt_assert(bucketptr != NULL && suftabptr < bucketptr);
        *bucketptr++ = (position > 0 &&
                        ((GtUword) array[position-1]) < currentcc)
                        ? ~position : position;
#ifdef SAINSHOWSTATE
        gt_assert(bucketptr != NULL);
        printf("L-induce: suftab[" GT_WU "]=" GT_WD "\n",
               (GtUword) (bucketptr-1-suftab),*(bucketptr-1));
#endif
      }
    }
  }
}

static void gt_sain_INTSEQ_induceStypesuffixes2(const GtSainseq *sainseq,
                                                 const GtUsainindextype *array,
                                         GtSsainindextype *suftab,
                                         GtUword nonspecialentries)
{
  GtUword lastupdatecc = 0;
  GtUsainindextype *fillptr = sainseq->bucketfillptr;

  GtSsainindextype *suftabptr, *bucketptr = NULL;

  gt_sain_special_singleSinduction2(sainseq,
                                    suftab,
                                    (GtSsainindextype) sainseq->totallength,
                                    nonspecialentries);
  if (sainseq->seqtype == GT_SAIN_ENCSEQ ||
      sainseq->seqtype == GT_SAIN_BARE_ENCSEQ)
  {
    gt_sain_induceStypes2fromspecialranges(sainseq,suftab,nonspecialentries);
  }
  for (suftabptr = suftab + nonspecialentries - 1; suftabptr >= suftab;
       suftabptr--)
  {
    GtSsainindextype position;
    if ((position = *suftabptr) > 0)
    {
      GtUword currentcc;

      position--;
      currentcc = (GtUword) array[position];
      if (currentcc < sainseq->numofchars)
      {
        GT_SAINUPDATEBUCKETPTR(currentcc);
        gt_assert(bucketptr != NULL && bucketptr - 1 < suftabptr);
        *(--bucketptr) = (position == 0 ||
                          ((GtUword) array[position-1]) > currentcc)
                         ? ~position : position;
#ifdef SAINSHOWSTATE
        gt_assert(bucketptr != NULL);
        printf("S-induce: suftab[" GT_WU "]=" GT_WD "\n",
                (GtUword) (bucketptr-suftab),*bucketptr);
#endif
      }
    } else
    {
      *suftabptr = ~position;
    }
  }
}
static int gt_sain_PLAINSEQ_compare_Sstarstrings(const GtSainseq *sainseq,
                                               const GtUchar *plainseq,
                                               GtUword start1,
                                               GtUword start2,
                                               GtUword len)
{
  GtUword end1 = start1 + len;

  gt_assert(start1 <= sainseq->totallength &&
            start2 <= sainseq->totallength &&
            start1 != start2);
  while (start1 < end1)
  {
    GtUword cc1, cc2;

    if (start1 == sainseq->totallength)
    {
      gt_assert(start1 > start2);
      return 1;
    }
    if (start2 == sainseq->totallength)
    {
      gt_assert(start1 < start2);
      return -1;
    }
    cc1 = (GtUword)
plainseq[start1];;
    cc2 = (GtUword)
plainseq[start2];;
    if (cc1 < cc2)
    {
      return -1;
    }
    if (cc1 > cc2)
    {
      return 1;
    }
    start1++;
    start2++;
  }
  return 0;
}
static void gt_sain_PLAINSEQ_expandorder2original(GtSainseq *sainseq,
                                                 const GtUchar *plainseq,
                                         GtUword numberofsuffixes,
                                         GtUsainindextype *suftab)
{
  GtUsainindextype *suftabptr,
                   position,
                   *sstarsuffixes = suftab + GT_MULT2(numberofsuffixes),
                   *sstarfirstcharcount = NULL,
                   *bucketsize = NULL;
  GtUword nextcc = GT_UNIQUEINT(sainseq->totallength);

  bool nextisStype = true;

  if (sainseq->seqtype == GT_SAIN_INTSEQ)
  {
    GtUword charidx;

    gt_assert(sainseq->sstarfirstcharcount == NULL);
    sstarfirstcharcount = sainseq->sstarfirstcharcount
                        = sainseq->bucketfillptr;
    bucketsize = sainseq->bucketsize;
    for (charidx = 0; charidx < sainseq->numofchars; charidx++)
    {
      sstarfirstcharcount[charidx] = 0;
      bucketsize[charidx] = 0;
    }
  }

  for (position = (GtUsainindextype) (sainseq->totallength-1); /* Nothing */;
       position--)
  {
    GtUword currentcc = (GtUword)
plainseq[position];
    bool currentisStype = (currentcc < nextcc ||
                           (currentcc == nextcc && nextisStype)) ? true : false;
    if (!currentisStype && nextisStype)
    {

      *--sstarsuffixes = position+1;
    }

    nextisStype = currentisStype;
    nextcc = currentcc;
    if (position == 0)
    {
      break;
    }
  }

  for (suftabptr = suftab; suftabptr < suftab + numberofsuffixes; suftabptr++)
  {
    *suftabptr = sstarsuffixes[*suftabptr];
  }
}

static GtUword gt_sain_PLAINSEQ_insertSstarsuffixes(GtSainseq *sainseq,
                                                 const GtUchar *plainseq,
                                                 GtUsainindextype *suftab,
                                                 GtLogger *logger)
{
  GtUword nextcc = GT_UNIQUEINT(sainseq->totallength),
          countSstartype = 0;
  GtUsainindextype position, *fillptr = sainseq->bucketfillptr;
  GtSainbuffer *sainbuffer = gt_sainbuffer_new(suftab,fillptr,
                                               sainseq->numofchars,
                                               sainseq->totallength,logger);

  bool nextisStype = true;

  gt_sain_endbuckets(sainseq);

  for (position = (GtUsainindextype) (sainseq->totallength-1); /* Nothing */;
       position--)
  {
    GtUword currentcc = (GtUword)
plainseq[position];
    bool currentisStype = (currentcc < nextcc ||
                           (currentcc == nextcc && nextisStype)) ? true : false;
    if (!currentisStype && nextisStype)
    {
      countSstartype++;
sainseq->sstarfirstcharcount[nextcc]++;
      if (sainbuffer != NULL)
      {
        gt_sainbuffer_update(sainbuffer,nextcc,position);
      } else
      {
        suftab[--fillptr[nextcc]] = position;
      }
#undef SAINSHOWSTATE
#ifdef SAINSHOWSTATE
      printf("Sstar.suftab[" GT_WU "]=" GT_WU "\n",fillptr[nextcc],position+1);
#endif
    }
    nextisStype = currentisStype;
    nextcc = currentcc;
    if (position == 0)
    {
      break;
    }
  }

  gt_sainbuffer_flushall(sainbuffer);
  gt_sainbuffer_delete(sainbuffer);
  gt_assert(GT_MULT2(countSstartype) <= sainseq->totallength);
  return countSstartype;
}

static void gt_sain_PLAINSEQ_assignSstarlength(GtSainseq *sainseq,
                                             const GtUchar *plainseq,
                                             GtUsainindextype *lentab)
{
  bool nextisStype = true;
  GtUsainindextype position,
                   nextSstartypepos = (GtUsainindextype) sainseq->totallength;

  GtUword nextcc = GT_UNIQUEINT(sainseq->totallength);

  for (position = (GtUsainindextype) (sainseq->totallength-1); /* Nothing */;
       position--)
  {
    GtUword currentcc = (GtUword)
plainseq[position];
    bool currentisStype = (currentcc < nextcc ||
                           (currentcc == nextcc && nextisStype)) ? true : false;
    if (!currentisStype && nextisStype)
    {
      gt_assert(position < nextSstartypepos);
      lentab[GT_DIV2(position+1)] = nextSstartypepos - position;
      nextSstartypepos = position + 1;
    }
    nextisStype = currentisStype;
    nextcc = currentcc;
    if (position == 0)
    {
      break;
    }
  }

}
static int gt_sain_ENCSEQ_compare_Sstarstrings(const GtSainseq *sainseq,
                                               const GtEncseq *encseq,
                                               GtUword start1,
                                               GtUword start2,
                                               GtUword len)
{
  GtUword end1 = start1 + len;

  gt_assert(start1 <= sainseq->totallength &&
            start2 <= sainseq->totallength &&
            start1 != start2);
  while (start1 < end1)
  {
    GtUword cc1, cc2;

    if (start1 == sainseq->totallength)
    {
      gt_assert(start1 > start2);
      return 1;
    }
    if (start2 == sainseq->totallength)
    {
      gt_assert(start1 < start2);
      return -1;
    }
    cc1 = (GtUword) gt_encseq_get_encoded_char(
encseq,
(GtUword) (start1),
sainseq->readmode);if (GT_ISSPECIAL(cc1)) { cc1 = GT_UNIQUEINT(start1); };
    cc2 = (GtUword) gt_encseq_get_encoded_char(
encseq,
(GtUword) (start2),
sainseq->readmode);if (GT_ISSPECIAL(cc2)) { cc2 = GT_UNIQUEINT(start2); };
    if (cc1 < cc2)
    {
      return -1;
    }
    if (cc1 > cc2)
    {
      return 1;
    }
    start1++;
    start2++;
  }
  return 0;
}
static void gt_sain_ENCSEQ_expandorder2original(GtSainseq *sainseq,
                                                 const GtEncseq *encseq,
                                         GtUword numberofsuffixes,
                                         GtUsainindextype *suftab)
{
  GtUsainindextype *suftabptr,
                   position,
                   *sstarsuffixes = suftab + GT_MULT2(numberofsuffixes),
                   *sstarfirstcharcount = NULL,
                   *bucketsize = NULL;
  GtUword nextcc = GT_UNIQUEINT(sainseq->totallength);
GtUchar tmpcc;
GtEncseqReader *esr;
  bool nextisStype = true;

  if (sainseq->seqtype == GT_SAIN_INTSEQ)
  {
    GtUword charidx;

    gt_assert(sainseq->sstarfirstcharcount == NULL);
    sstarfirstcharcount = sainseq->sstarfirstcharcount
                        = sainseq->bucketfillptr;
    bucketsize = sainseq->bucketsize;
    for (charidx = 0; charidx < sainseq->numofchars; charidx++)
    {
      sstarfirstcharcount[charidx] = 0;
      bucketsize[charidx] = 0;
    }
  }
esr = gt_encseq_create_reader_with_readmode(
                            encseq,
                            gt_readmode_inverse_direction(sainseq->readmode),
                            0);
  for (position = (GtUsainindextype) (sainseq->totallength-1); /* Nothing */;
       position--)
  {
    GtUword currentcc = GT_ISSPECIAL(tmpcc =
gt_encseq_reader_next_encoded_char(esr))
 ? GT_UNIQUEINT(position) : (GtUword) tmpcc;
    bool currentisStype = (currentcc < nextcc ||
                           (currentcc == nextcc && nextisStype)) ? true : false;
    if (!currentisStype && nextisStype)
    {

      *--sstarsuffixes = position+1;
    }

    nextisStype = currentisStype;
    nextcc = currentcc;
    if (position == 0)
    {
      break;
    }
  }
gt_encseq_reader_delete(esr);
  for (suftabptr = suftab; suftabptr < suftab + numberofsuffixes; suftabptr++)
  {
    *suftabptr = sstarsuffixes[*suftabptr];
  }
}

static GtUword gt_sain_ENCSEQ_insertSstarsuffixes(GtSainseq *sainseq,
                                                 const GtEncseq *encseq,
                                                 GtUsainindextype *suftab,
                                                 GtLogger *logger)
{
  GtUword nextcc = GT_UNIQUEINT(sainseq->totallength),
          countSstartype = 0;
  GtUsainindextype position, *fillptr = sainseq->bucketfillptr;
  GtSainbuffer *sainbuffer = gt_sainbuffer_new(suftab,fillptr,
                                               sainseq->numofchars,
                                               sainseq->totallength,logger);
GtUchar tmpcc;
GtEncseqReader *esr;
  bool nextisStype = true;

  gt_sain_endbuckets(sainseq);
esr = gt_encseq_create_reader_with_readmode(
                            encseq,
                            gt_readmode_inverse_direction(sainseq->readmode),
                            0);
  for (position = (GtUsainindextype) (sainseq->totallength-1); /* Nothing */;
       position--)
  {
    GtUword currentcc = GT_ISSPECIAL(tmpcc =
gt_encseq_reader_next_encoded_char(esr))
 ? GT_UNIQUEINT(position) : (GtUword) tmpcc;
    bool currentisStype = (currentcc < nextcc ||
                           (currentcc == nextcc && nextisStype)) ? true : false;
    if (!currentisStype && nextisStype)
    {
      countSstartype++;
sainseq->sstarfirstcharcount[nextcc]++;
      if (sainbuffer != NULL)
      {
        gt_sainbuffer_update(sainbuffer,nextcc,position);
      } else
      {
        suftab[--fillptr[nextcc]] = position;
      }
#undef SAINSHOWSTATE
#ifdef SAINSHOWSTATE
      printf("Sstar.suftab[" GT_WU "]=" GT_WU "\n",fillptr[nextcc],position+1);
#endif
    }
    nextisStype = currentisStype;
    nextcc = currentcc;
    if (position == 0)
    {
      break;
    }
  }
gt_encseq_reader_delete(esr);
  gt_sainbuffer_flushall(sainbuffer);
  gt_sainbuffer_delete(sainbuffer);
  gt_assert(GT_MULT2(countSstartype) <= sainseq->totallength);
  return countSstartype;
}

static void gt_sain_ENCSEQ_assignSstarlength(GtSainseq *sainseq,
                                             const GtEncseq *encseq,
                                             GtUsainindextype *lentab)
{
  bool nextisStype = true;
  GtUsainindextype position,
                   nextSstartypepos = (GtUsainindextype) sainseq->totallength;
GtUchar tmpcc;
GtEncseqReader *esr;
  GtUword nextcc = GT_UNIQUEINT(sainseq->totallength);
esr = gt_encseq_create_reader_with_readmode(
                            encseq,
                            gt_readmode_inverse_direction(sainseq->readmode),
                            0);
  for (position = (GtUsainindextype) (sainseq->totallength-1); /* Nothing */;
       position--)
  {
    GtUword currentcc = GT_ISSPECIAL(tmpcc =
gt_encseq_reader_next_encoded_char(esr))
 ? GT_UNIQUEINT(position) : (GtUword) tmpcc;
    bool currentisStype = (currentcc < nextcc ||
                           (currentcc == nextcc && nextisStype)) ? true : false;
    if (!currentisStype && nextisStype)
    {
      gt_assert(position < nextSstartypepos);
      lentab[GT_DIV2(position+1)] = nextSstartypepos - position;
      nextSstartypepos = position + 1;
    }
    nextisStype = currentisStype;
    nextcc = currentcc;
    if (position == 0)
    {
      break;
    }
  }
gt_encseq_reader_delete(esr);
}
static int gt_sain_BARE_ENCSEQ_compare_Sstarstrings(const GtSainseq *sainseq,
                                               const GtUchar *plainseq,
                                               GtUword start1,
                                               GtUword start2,
                                               GtUword len)
{
  GtUword end1 = start1 + len;

  gt_assert(start1 <= sainseq->totallength &&
            start2 <= sainseq->totallength &&
            start1 != start2);
  while (start1 < end1)
  {
    GtUword cc1, cc2;

    if (start1 == sainseq->totallength)
    {
      gt_assert(start1 > start2);
      return 1;
    }
    if (start2 == sainseq->totallength)
    {
      gt_assert(start1 < start2);
      return -1;
    }
    cc1 = (GtUword)
plainseq[start1];if (GT_ISSPECIAL(cc1)) { cc1 = GT_UNIQUEINT(start1); };
    cc2 = (GtUword)
plainseq[start2];if (GT_ISSPECIAL(cc2)) { cc2 = GT_UNIQUEINT(start2); };
    if (cc1 < cc2)
    {
      return -1;
    }
    if (cc1 > cc2)
    {
      return 1;
    }
    start1++;
    start2++;
  }
  return 0;
}
static void gt_sain_BARE_ENCSEQ_expandorder2original(GtSainseq *sainseq,
                                                 const GtUchar *plainseq,
                                         GtUword numberofsuffixes,
                                         GtUsainindextype *suftab)
{
  GtUsainindextype *suftabptr,
                   position,
                   *sstarsuffixes = suftab + GT_MULT2(numberofsuffixes),
                   *sstarfirstcharcount = NULL,
                   *bucketsize = NULL;
  GtUword nextcc = GT_UNIQUEINT(sainseq->totallength);
GtUchar tmpcc;
  bool nextisStype = true;

  if (sainseq->seqtype == GT_SAIN_INTSEQ)
  {
    GtUword charidx;

    gt_assert(sainseq->sstarfirstcharcount == NULL);
    sstarfirstcharcount = sainseq->sstarfirstcharcount
                        = sainseq->bucketfillptr;
    bucketsize = sainseq->bucketsize;
    for (charidx = 0; charidx < sainseq->numofchars; charidx++)
    {
      sstarfirstcharcount[charidx] = 0;
      bucketsize[charidx] = 0;
    }
  }

  for (position = (GtUsainindextype) (sainseq->totallength-1); /* Nothing */;
       position--)
  {
    GtUword currentcc = (GtUword)
GT_ISSPECIAL(tmpcc =
plainseq[position])
  ? GT_UNIQUEINT(position) : (GtUword) tmpcc;
    bool currentisStype = (currentcc < nextcc ||
                           (currentcc == nextcc && nextisStype)) ? true : false;
    if (!currentisStype && nextisStype)
    {

      *--sstarsuffixes = position+1;
    }

    nextisStype = currentisStype;
    nextcc = currentcc;
    if (position == 0)
    {
      break;
    }
  }

  for (suftabptr = suftab; suftabptr < suftab + numberofsuffixes; suftabptr++)
  {
    *suftabptr = sstarsuffixes[*suftabptr];
  }
}

static GtUword gt_sain_BARE_ENCSEQ_insertSstarsuffixes(GtSainseq *sainseq,
                                                 const GtUchar *plainseq,
                                                 GtUsainindextype *suftab,
                                                 GtLogger *logger)
{
  GtUword nextcc = GT_UNIQUEINT(sainseq->totallength),
          countSstartype = 0;
  GtUsainindextype position, *fillptr = sainseq->bucketfillptr;
  GtSainbuffer *sainbuffer = gt_sainbuffer_new(suftab,fillptr,
                                               sainseq->numofchars,
                                               sainseq->totallength,logger);
GtUchar tmpcc;
  bool nextisStype = true;

  gt_sain_endbuckets(sainseq);

  for (position = (GtUsainindextype) (sainseq->totallength-1); /* Nothing */;
       position--)
  {
    GtUword currentcc = (GtUword)
GT_ISSPECIAL(tmpcc =
plainseq[position])
  ? GT_UNIQUEINT(position) : (GtUword) tmpcc;
    bool currentisStype = (currentcc < nextcc ||
                           (currentcc == nextcc && nextisStype)) ? true : false;
    if (!currentisStype && nextisStype)
    {
      countSstartype++;
sainseq->sstarfirstcharcount[nextcc]++;
      if (sainbuffer != NULL)
      {
        gt_sainbuffer_update(sainbuffer,nextcc,position);
      } else
      {
        suftab[--fillptr[nextcc]] = position;
      }
#undef SAINSHOWSTATE
#ifdef SAINSHOWSTATE
      printf("Sstar.suftab[" GT_WU "]=" GT_WU "\n",fillptr[nextcc],position+1);
#endif
    }
    nextisStype = currentisStype;
    nextcc = currentcc;
    if (position == 0)
    {
      break;
    }
  }

  gt_sainbuffer_flushall(sainbuffer);
  gt_sainbuffer_delete(sainbuffer);
  gt_assert(GT_MULT2(countSstartype) <= sainseq->totallength);
  return countSstartype;
}

static void gt_sain_BARE_ENCSEQ_assignSstarlength(GtSainseq *sainseq,
                                             const GtUchar *plainseq,
                                             GtUsainindextype *lentab)
{
  bool nextisStype = true;
  GtUsainindextype position,
                   nextSstartypepos = (GtUsainindextype) sainseq->totallength;
GtUchar tmpcc;
  GtUword nextcc = GT_UNIQUEINT(sainseq->totallength);

  for (position = (GtUsainindextype) (sainseq->totallength-1); /* Nothing */;
       position--)
  {
    GtUword currentcc = (GtUword)
GT_ISSPECIAL(tmpcc =
plainseq[position])
  ? GT_UNIQUEINT(position) : (GtUword) tmpcc;
    bool currentisStype = (currentcc < nextcc ||
                           (currentcc == nextcc && nextisStype)) ? true : false;
    if (!currentisStype && nextisStype)
    {
      gt_assert(position < nextSstartypepos);
      lentab[GT_DIV2(position+1)] = nextSstartypepos - position;
      nextSstartypepos = position + 1;
    }
    nextisStype = currentisStype;
    nextcc = currentcc;
    if (position == 0)
    {
      break;
    }
  }

}
static int gt_sain_INTSEQ_compare_Sstarstrings(const GtSainseq *sainseq,
                                               const GtUsainindextype *array,
                                               GtUword start1,
                                               GtUword start2,
                                               GtUword len)
{
  GtUword end1 = start1 + len;

  gt_assert(start1 <= sainseq->totallength &&
            start2 <= sainseq->totallength &&
            start1 != start2);
  while (start1 < end1)
  {
    GtUword cc1, cc2;

    if (start1 == sainseq->totallength)
    {
      gt_assert(start1 > start2);
      return 1;
    }
    if (start2 == sainseq->totallength)
    {
      gt_assert(start1 < start2);
      return -1;
    }
    cc1 = (GtUword) array[start1];;
    cc2 = (GtUword) array[start2];;
    if (cc1 < cc2)
    {
      return -1;
    }
    if (cc1 > cc2)
    {
      return 1;
    }
    start1++;
    start2++;
  }
  return 0;
}
static void gt_sain_INTSEQ_expandorder2original(GtSainseq *sainseq,
                                                 const GtUsainindextype *array,
                                         GtUword numberofsuffixes,
                                         GtUsainindextype *suftab)
{
  GtUsainindextype *suftabptr,
                   position,
                   *sstarsuffixes = suftab + GT_MULT2(numberofsuffixes),
                   *sstarfirstcharcount = NULL,
                   *bucketsize = NULL;
  GtUword nextcc = GT_UNIQUEINT(sainseq->totallength);

  bool nextisStype = true;

  if (sainseq->seqtype == GT_SAIN_INTSEQ)
  {
    GtUword charidx;

    gt_assert(sainseq->sstarfirstcharcount == NULL);
    sstarfirstcharcount = sainseq->sstarfirstcharcount
                        = sainseq->bucketfillptr;
    bucketsize = sainseq->bucketsize;
    for (charidx = 0; charidx < sainseq->numofchars; charidx++)
    {
      sstarfirstcharcount[charidx] = 0;
      bucketsize[charidx] = 0;
    }
  }
gt_assert(bucketsize != NULL && sstarfirstcharcount != NULL);
  for (position = (GtUsainindextype) (sainseq->totallength-1); /* Nothing */;
       position--)
  {
    GtUword currentcc = (GtUword) array[position];
    bool currentisStype = (currentcc < nextcc ||
                           (currentcc == nextcc && nextisStype)) ? true : false;
    if (!currentisStype && nextisStype)
    {
sstarfirstcharcount[nextcc]++;
      *--sstarsuffixes = position+1;
    }
bucketsize[currentcc]++;
    nextisStype = currentisStype;
    nextcc = currentcc;
    if (position == 0)
    {
      break;
    }
  }

  for (suftabptr = suftab; suftabptr < suftab + numberofsuffixes; suftabptr++)
  {
    *suftabptr = sstarsuffixes[*suftabptr];
  }
}

static GtUword gt_sain_INTSEQ_insertSstarsuffixes(GtSainseq *sainseq,
                                                 const GtUsainindextype *array,
                                                 GtUsainindextype *suftab,
                                                 GtLogger *logger)
{
  GtUword nextcc = GT_UNIQUEINT(sainseq->totallength),
          countSstartype = 0;
  GtUsainindextype position, *fillptr = sainseq->bucketfillptr;
  GtSainbuffer *sainbuffer = gt_sainbuffer_new(suftab,fillptr,
                                               sainseq->numofchars,
                                               sainseq->totallength,logger);

  bool nextisStype = true;

  gt_sain_endbuckets(sainseq);

  for (position = (GtUsainindextype) (sainseq->totallength-1); /* Nothing */;
       position--)
  {
    GtUword currentcc = (GtUword) array[position];
    bool currentisStype = (currentcc < nextcc ||
                           (currentcc == nextcc && nextisStype)) ? true : false;
    if (!currentisStype && nextisStype)
    {
      countSstartype++;

      if (sainbuffer != NULL)
      {
        gt_sainbuffer_update(sainbuffer,nextcc,position);
      } else
      {
        suftab[--fillptr[nextcc]] = position;
      }
#undef SAINSHOWSTATE
#ifdef SAINSHOWSTATE
      printf("Sstar.suftab[" GT_WU "]=" GT_WU "\n",fillptr[nextcc],position+1);
#endif
    }
    nextisStype = currentisStype;
    nextcc = currentcc;
    if (position == 0)
    {
      break;
    }
  }

  gt_sainbuffer_flushall(sainbuffer);
  gt_sainbuffer_delete(sainbuffer);
  gt_assert(GT_MULT2(countSstartype) <= sainseq->totallength);
  return countSstartype;
}

static void gt_sain_INTSEQ_assignSstarlength(GtSainseq *sainseq,
                                             const GtUsainindextype *array,
                                             GtUsainindextype *lentab)
{
  bool nextisStype = true;
  GtUsainindextype position,
                   nextSstartypepos = (GtUsainindextype) sainseq->totallength;

  GtUword nextcc = GT_UNIQUEINT(sainseq->totallength);

  for (position = (GtUsainindextype) (sainseq->totallength-1); /* Nothing */;
       position--)
  {
    GtUword currentcc = (GtUword) array[position];
    bool currentisStype = (currentcc < nextcc ||
                           (currentcc == nextcc && nextisStype)) ? true : false;
    if (!currentisStype && nextisStype)
    {
      gt_assert(position < nextSstartypepos);
      lentab[GT_DIV2(position+1)] = nextSstartypepos - position;
      nextSstartypepos = position + 1;
    }
    nextisStype = currentisStype;
    nextcc = currentcc;
    if (position == 0)
    {
      break;
    }
  }

}
