/* Code generated by HMMoC version 1.3, Copyright (C) 2006 Gerton Lunter */
/* Generated from file aminoacid_indel2.xml (author:  Robert K. Bradley ) on Tue Dec 23 01:04:18 CST 2008 */

/*
This file is a work based on HMMoC 1.3, a hidden Markov model compiler.
Copyright (C) 2006 by Gerton Lunter, Oxford University.

HMMoC and works based on it are free software; you can redistribute 
it and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.

HMMOC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with HMMoC; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/


#include "aminoacid_indel2dp.h"

#include "mybanding.h"

const extern string _AminoAcidIndel2AlignstateId[];
const extern string _AminoAcidIndel2AlignemissionId[];
const extern string _AminoAcidIndel2AligntransitionId[];
const extern string _AminoAcidIndel2AligntransF[];
const extern string _AminoAcidIndel2AligntransT[];
const extern string _AminoAcidIndel2AligntransP[];
const extern string _AminoAcidIndel2AligntransE[];
const extern string _AminoAcidIndel2AlignoutputId[];
const extern string _AminoAcidIndel2Alignempty;
const extern int _AminoAcidIndel2AlignstateNum;
const extern int _AminoAcidIndel2AlignemitNum;
const extern int _AminoAcidIndel2AligntransNum;
const extern int _AminoAcidIndel2AlignoutputNum;

AminoAcidIndel2AlignDPTable::AminoAcidIndel2AlignDPTable(int iLen1,int iLen2) : isInCharge(true), stateId(_AminoAcidIndel2AlignstateId), emissionId(_AminoAcidIndel2AlignemissionId), transitionId(_AminoAcidIndel2AligntransitionId), transitionFrom(_AminoAcidIndel2AligntransF), transitionTo(_AminoAcidIndel2AligntransT), transitionProb(_AminoAcidIndel2AligntransP), transitionEmit(_AminoAcidIndel2AligntransE), outputId(_AminoAcidIndel2AlignoutputId) {
    // init code:
    this->iLen1 = iLen1;
    this->iLen2 = iLen2;
    StateMemoryaaIndel2Block2.allocate(1+iLen1, 1+iLen2);
    StateMemoryaaIndel2Block1.allocate();
    StateMemoryaaIndel2Block3.allocate();
}


AminoAcidIndel2AlignDPTable::~AminoAcidIndel2AlignDPTable() {
    if (!isInCharge) {
        // make sure data does not get deleted:
        StateMemoryaaIndel2Block2.absolve();
        StateMemoryaaIndel2Block1.absolve();
        StateMemoryaaIndel2Block3.absolve();
    } // if(!isInCharge)
} // destructor

const string& AminoAcidIndel2AlignDPTable::getTransitionId(int id) { return id>=0 && id<_AminoAcidIndel2AligntransNum ? _AminoAcidIndel2AligntransitionId[id] : _AminoAcidIndel2Alignempty; }
const string& AminoAcidIndel2AlignDPTable::getEmissionId(int id) { return id>=0 && id<_AminoAcidIndel2AlignemitNum ? _AminoAcidIndel2AlignemissionId[id] : _AminoAcidIndel2Alignempty; }
const string& AminoAcidIndel2AlignDPTable::getStateId(int id) { return id>=0 && id<_AminoAcidIndel2AlignstateNum ? _AminoAcidIndel2AlignstateId[id] : _AminoAcidIndel2Alignempty; }
const string& AminoAcidIndel2AlignDPTable::getOutputId(int id) { return id>=0 && id<_AminoAcidIndel2AlignoutputNum ? _AminoAcidIndel2AlignoutputId[id] : _AminoAcidIndel2Alignempty; }
int AminoAcidIndel2AlignDPTable::getId(const string& sId)
{
    static bool bInit = false;
    static map<string,int>* pmId;
    if (!bInit) {
        pmId = new map<string,int>();
        for (int i=0;i<_AminoAcidIndel2AlignstateNum;i++) {
            (*pmId)[_AminoAcidIndel2AlignstateId[i]] = i;         // add state identifiers
        }
        for (int i=0; i<_AminoAcidIndel2AlignemitNum; i++) {
            (*pmId)[_AminoAcidIndel2AlignemissionId[i]] = i;      // add emission identifiers
        }
        for (int i=0; i<_AminoAcidIndel2AligntransNum; i++) {  
            (*pmId)[_AminoAcidIndel2AligntransitionId[i]] = i;    // add transition identifiers
        }
        for (int i=0; i<_AminoAcidIndel2AlignoutputNum; i++) {
            (*pmId)[_AminoAcidIndel2AlignoutputId[i]] = i;        // finally, add output identifiers
        }
        bInit = true;
    }
    map<string,int>::iterator iter = pmId->find(sId);
    if (iter == pmId->end()) {
        if (sId == "_cleanup_") {
            delete pmId;
            } else {
            cout << "AminoAcidIndel2AlignDPTable::getId: WARNING: identifier '" << sId << "' not found." << endl;
        }
        return -1;
    }
    return iter->second;
}


bfloat AminoAcidIndel2AlignDPTable::getProb(const string sState ,int iPos0,int iPos1) const
{
    return getProb(getId(sState) ,iPos0,iPos1);
}


bfloat AminoAcidIndel2AlignDPTable::getProb(int iState ,int iPos0,int iPos1) const
{
    const bfloat *CurStateMemoryaaIndel2Block1Secondary;
    const bfloat *CurStateMemoryaaIndel2Block2Secondary;
    const bfloat *CurStateMemoryaaIndel2Block3Secondary;
    static const int blockTable[] = {0, 1, 1, 1, 1, 1, 2};
    static const int stateTable[] = {0, 0, 1, 2, 3, 4, 0};
    switch (blockTable[iState]) {
        default:
        return 0.0;
        break;
        case 0:
        if ((iPos0+0>=0)&&(iPos0+0<=0)&&(iPos1+0>=0)&&(iPos1+0<=0)) {
            CurStateMemoryaaIndel2Block1Secondary = this->StateMemoryaaIndel2Block1.read();
            return CurStateMemoryaaIndel2Block1Secondary[stateTable[iState]];
        } 
        else { 
            return 0.0;
            
        }
        break;
        case 1:
        if ((iPos0+0>=0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=0)&&(iPos1+0<=iLen2+0)) {
            CurStateMemoryaaIndel2Block2Secondary = this->StateMemoryaaIndel2Block2.read((iPos0-(0))-(0), (iPos1-(0))-(0));
            return CurStateMemoryaaIndel2Block2Secondary[stateTable[iState]];
        } 
        else { 
            return 0.0;
            
        }
        break;
        case 2:
        if ((iPos0+0>=iLen1+0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=iLen2+0)&&(iPos1+0<=iLen2+0)) {
            CurStateMemoryaaIndel2Block3Secondary = this->StateMemoryaaIndel2Block3.read();
            return CurStateMemoryaaIndel2Block3Secondary[stateTable[iState]];
        } 
        else { 
            return 0.0;
            
        }
    } // switch
} // DPTable...::getProb(int,...)

const extern string _AminoAcidIndel2AlignstateId[];
const extern string _AminoAcidIndel2AlignemissionId[];
const extern string _AminoAcidIndel2AligntransitionId[];
const extern string _AminoAcidIndel2AligntransF[];
const extern string _AminoAcidIndel2AligntransT[];
const extern string _AminoAcidIndel2AligntransP[];
const extern string _AminoAcidIndel2AligntransE[];
const extern string _AminoAcidIndel2AlignoutputId[];
const extern string _AminoAcidIndel2Alignempty;
const extern int _AminoAcidIndel2AlignstateNum;
const extern int _AminoAcidIndel2AlignemitNum;
const extern int _AminoAcidIndel2AligntransNum;
const extern int _AminoAcidIndel2AlignoutputNum;

AminoAcidIndel2AlignFoldedDPTable::AminoAcidIndel2AlignFoldedDPTable(int iLen1,int iLen2) : isInCharge(true), stateId(_AminoAcidIndel2AlignstateId), emissionId(_AminoAcidIndel2AlignemissionId), transitionId(_AminoAcidIndel2AligntransitionId), transitionFrom(_AminoAcidIndel2AligntransF), transitionTo(_AminoAcidIndel2AligntransT), transitionProb(_AminoAcidIndel2AligntransP), transitionEmit(_AminoAcidIndel2AligntransE), outputId(_AminoAcidIndel2AlignoutputId) {
    // init code:
    this->iLen1 = iLen1;
    this->iLen2 = iLen2;
    StateMemoryaaIndel2Block2.allocate(1+iLen1, 1+iLen2);
    StateMemoryaaIndel2Block3.allocate();
    StateMemoryaaIndel2Block1.allocate();
}


AminoAcidIndel2AlignFoldedDPTable::~AminoAcidIndel2AlignFoldedDPTable() {
    if (!isInCharge) {
        // make sure data does not get deleted:
        StateMemoryaaIndel2Block2.absolve();
        StateMemoryaaIndel2Block3.absolve();
        StateMemoryaaIndel2Block1.absolve();
    } // if(!isInCharge)
} // destructor

const string& AminoAcidIndel2AlignFoldedDPTable::getTransitionId(int id) { return id>=0 && id<_AminoAcidIndel2AligntransNum ? _AminoAcidIndel2AligntransitionId[id] : _AminoAcidIndel2Alignempty; }
const string& AminoAcidIndel2AlignFoldedDPTable::getEmissionId(int id) { return id>=0 && id<_AminoAcidIndel2AlignemitNum ? _AminoAcidIndel2AlignemissionId[id] : _AminoAcidIndel2Alignempty; }
const string& AminoAcidIndel2AlignFoldedDPTable::getStateId(int id) { return id>=0 && id<_AminoAcidIndel2AlignstateNum ? _AminoAcidIndel2AlignstateId[id] : _AminoAcidIndel2Alignempty; }
const string& AminoAcidIndel2AlignFoldedDPTable::getOutputId(int id) { return id>=0 && id<_AminoAcidIndel2AlignoutputNum ? _AminoAcidIndel2AlignoutputId[id] : _AminoAcidIndel2Alignempty; }
int AminoAcidIndel2AlignFoldedDPTable::getId(const string& sId)
{
    static bool bInit = false;
    static map<string,int>* pmId;
    if (!bInit) {
        pmId = new map<string,int>();
        for (int i=0;i<_AminoAcidIndel2AlignstateNum;i++) {
            (*pmId)[_AminoAcidIndel2AlignstateId[i]] = i;         // add state identifiers
        }
        for (int i=0; i<_AminoAcidIndel2AlignemitNum; i++) {
            (*pmId)[_AminoAcidIndel2AlignemissionId[i]] = i;      // add emission identifiers
        }
        for (int i=0; i<_AminoAcidIndel2AligntransNum; i++) {  
            (*pmId)[_AminoAcidIndel2AligntransitionId[i]] = i;    // add transition identifiers
        }
        for (int i=0; i<_AminoAcidIndel2AlignoutputNum; i++) {
            (*pmId)[_AminoAcidIndel2AlignoutputId[i]] = i;        // finally, add output identifiers
        }
        bInit = true;
    }
    map<string,int>::iterator iter = pmId->find(sId);
    if (iter == pmId->end()) {
        if (sId == "_cleanup_") {
            delete pmId;
            } else {
            cout << "AminoAcidIndel2AlignFoldedDPTable::getId: WARNING: identifier '" << sId << "' not found." << endl;
        }
        return -1;
    }
    return iter->second;
}


bfloat AminoAcidIndel2AlignFoldedDPTable::getProb(const string sState ,int iPos0,int iPos1) const
{
    return getProb(getId(sState) ,iPos0,iPos1);
}


bfloat AminoAcidIndel2AlignFoldedDPTable::getProb(int iState ,int iPos0,int iPos1) const
{
    const bfloat *CurStateMemoryaaIndel2Block1Secondary;
    const bfloat *CurStateMemoryaaIndel2Block2Secondary;
    const bfloat *CurStateMemoryaaIndel2Block3Secondary;
    static const int blockTable[] = {0, 1, 1, 1, 1, 1, 2};
    static const int stateTable[] = {0, 0, 1, 2, 3, 4, 0};
    switch (blockTable[iState]) {
        default:
        return 0.0;
        break;
        case 0:
        if ((iPos0+0>=0)&&(iPos0+0<=0)&&(iPos1+0>=0)&&(iPos1+0<=0)) {
            CurStateMemoryaaIndel2Block1Secondary = this->StateMemoryaaIndel2Block1.read();
            return CurStateMemoryaaIndel2Block1Secondary[stateTable[iState]];
        } 
        else { 
            return 0.0;
            
        }
        break;
        case 1:
        if ((iPos0+0>=0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=0)&&(iPos1+0<=iLen2+0)) {
            CurStateMemoryaaIndel2Block2Secondary = this->StateMemoryaaIndel2Block2.read((iPos0-(0))-(0), (iPos1-(0))-(0));
            return CurStateMemoryaaIndel2Block2Secondary[stateTable[iState]];
        } 
        else { 
            return 0.0;
            
        }
        break;
        case 2:
        if ((iPos0+0>=iLen1+0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=iLen2+0)&&(iPos1+0<=iLen2+0)) {
            CurStateMemoryaaIndel2Block3Secondary = this->StateMemoryaaIndel2Block3.read();
            return CurStateMemoryaaIndel2Block3Secondary[stateTable[iState]];
        } 
        else { 
            return 0.0;
            
        }
    } // switch
} // DPTable...::getProb(int,...)

int AminoAcidIndel2AlignBaumWelch::transitionIndex(string strId) const {
    map<const string,int>::const_iterator iter = mId.find(strId);
    if (iter == mId.end()) {
        cout << "AminoAcidIndel2AlignBaumWelch::transitionIndex: WARNING: identifier '" << strId << "' not found." << endl;
        return -1;
    }
    return iter->second;
}


int AminoAcidIndel2AlignBaumWelch::emissionIndex(string strId) const {
    map<const string,int>::const_iterator iter = mId.find(strId);
    if (iter == mId.end()) {
        cout << "AminoAcidIndel2AlignBaumWelch::emissionIndex: WARNING: identifier '" << strId << "' not found." << endl;
        return -1;
    }
    return iter->second;
}


void AminoAcidIndel2AlignBaumWelch::resetCounts() {
    static bool bInited = false;
    if (!bInited) {
        static const int aTemp[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22};
        for (int i=0; i<23; i++) {
            transitionIdentifier00[i] = aTemp[i];
            atransitionIdx[aTemp[i]] = i;
            mId[_AminoAcidIndel2AligntransitionId[aTemp[i]]] = i;
        }
    }
    for (int i=0; i<23; i++) {
        
        transitionBaumWelchCount00[i] = 0.0;
    }
    if (!bInited) {
        static const int aTemp[] = {2};
        for (int i=0; i<1; i++) {
            emissionIdentifier00[i] = aTemp[i];
            aemissionIdx[aTemp[i]] = i;
            mId[_AminoAcidIndel2AlignemissionId[aTemp[i]]] = i;
        }
    }
    for (int i=0; i<1; i++) {
        
        emissionBaumWelchCount00[i] = 0.0;
    }
    if (!bInited) {
        static const int aTemp[] = {1};
        for (int i=0; i<1; i++) {
            emissionIdentifier01[i] = aTemp[i];
            aemissionIdx[aTemp[i]] = i;
            mId[_AminoAcidIndel2AlignemissionId[aTemp[i]]] = i;
        }
    }
    for (int i=0; i<1; i++) {
        for(int v10=0;v10<20;v10++)
        emissionBaumWelchCount01[v10][i] = 0.0;
    }
    if (!bInited) {
        static const int aTemp[] = {3};
        for (int i=0; i<1; i++) {
            emissionIdentifier10[i] = aTemp[i];
            aemissionIdx[aTemp[i]] = i;
            mId[_AminoAcidIndel2AlignemissionId[aTemp[i]]] = i;
        }
    }
    for (int i=0; i<1; i++) {
        for(int v00=0;v00<20;v00++)
        emissionBaumWelchCount10[v00][i] = 0.0;
    }
    if (!bInited) {
        static const int aTemp[] = {0};
        for (int i=0; i<1; i++) {
            emissionIdentifier11[i] = aTemp[i];
            aemissionIdx[aTemp[i]] = i;
            mId[_AminoAcidIndel2AlignemissionId[aTemp[i]]] = i;
        }
    }
    for (int i=0; i<1; i++) {
        for(int v00=0;v00<20;v00++)for(int v10=0;v10<20;v10++)
        emissionBaumWelchCount11[v00][v10][i] = 0.0;
    }
    bInited = true;
};


int AminoAcidIndel2AlignBaumWelch::transitionIdentifier00[];
int AminoAcidIndel2AlignBaumWelch::emissionIdentifier00[];
int AminoAcidIndel2AlignBaumWelch::emissionIdentifier01[];
int AminoAcidIndel2AlignBaumWelch::emissionIdentifier10[];
int AminoAcidIndel2AlignBaumWelch::emissionIdentifier11[];

void AminoAcidIndel2AlignBaumWelch::scaleCounts(bfloat scale) {
    for (int i=0; i<23; i++) {
        
        transitionBaumWelchCount00[i] *= scale;
    }
    for (int i=0; i<1; i++) {
        
        emissionBaumWelchCount00[i] *= scale;
    }
    for (int i=0; i<1; i++) {
        for(int v10=0;v10<20;v10++)
        emissionBaumWelchCount01[v10][i] *= scale;
    }
    for (int i=0; i<1; i++) {
        for(int v00=0;v00<20;v00++)
        emissionBaumWelchCount10[v00][i] *= scale;
    }
    for (int i=0; i<1; i++) {
        for(int v00=0;v00<20;v00++)for(int v10=0;v10<20;v10++)
        emissionBaumWelchCount11[v00][v10][i] *= scale;
    }
}


map<const string,int> AminoAcidIndel2AlignBaumWelch::mId;
int AminoAcidIndel2AlignBaumWelch::atransitionIdx[];
int AminoAcidIndel2AlignBaumWelch::aemissionIdx[];

const extern string _AminoAcidIndel2AlignWithBandingstateId[];
const extern string _AminoAcidIndel2AlignWithBandingemissionId[];
const extern string _AminoAcidIndel2AlignWithBandingtransitionId[];
const extern string _AminoAcidIndel2AlignWithBandingtransF[];
const extern string _AminoAcidIndel2AlignWithBandingtransT[];
const extern string _AminoAcidIndel2AlignWithBandingtransP[];
const extern string _AminoAcidIndel2AlignWithBandingtransE[];
const extern string _AminoAcidIndel2AlignWithBandingoutputId[];
const extern string _AminoAcidIndel2AlignWithBandingempty;
const extern int _AminoAcidIndel2AlignWithBandingstateNum;
const extern int _AminoAcidIndel2AlignWithBandingemitNum;
const extern int _AminoAcidIndel2AlignWithBandingtransNum;
const extern int _AminoAcidIndel2AlignWithBandingoutputNum;

AminoAcidIndel2AlignWithBandingDPTable::AminoAcidIndel2AlignWithBandingDPTable(int iLen1,int iLen2) : isInCharge(true), stateId(_AminoAcidIndel2AlignWithBandingstateId), emissionId(_AminoAcidIndel2AlignWithBandingemissionId), transitionId(_AminoAcidIndel2AlignWithBandingtransitionId), transitionFrom(_AminoAcidIndel2AlignWithBandingtransF), transitionTo(_AminoAcidIndel2AlignWithBandingtransT), transitionProb(_AminoAcidIndel2AlignWithBandingtransP), transitionEmit(_AminoAcidIndel2AlignWithBandingtransE), outputId(_AminoAcidIndel2AlignWithBandingoutputId) {
    // init code:
    this->iLen1 = iLen1;
    this->iLen2 = iLen2;
    StateMemoryaaIndel2Block2withbanding.allocate(1+iLen1, 1+iLen2);
    StateMemoryaaIndel2Block1.allocate();
    StateMemoryaaIndel2Block3.allocate();
}


AminoAcidIndel2AlignWithBandingDPTable::~AminoAcidIndel2AlignWithBandingDPTable() {
    if (!isInCharge) {
        // make sure data does not get deleted:
        StateMemoryaaIndel2Block2withbanding.absolve();
        StateMemoryaaIndel2Block1.absolve();
        StateMemoryaaIndel2Block3.absolve();
    } // if(!isInCharge)
} // destructor

const string& AminoAcidIndel2AlignWithBandingDPTable::getTransitionId(int id) { return id>=0 && id<_AminoAcidIndel2AlignWithBandingtransNum ? _AminoAcidIndel2AlignWithBandingtransitionId[id] : _AminoAcidIndel2AlignWithBandingempty; }
const string& AminoAcidIndel2AlignWithBandingDPTable::getEmissionId(int id) { return id>=0 && id<_AminoAcidIndel2AlignWithBandingemitNum ? _AminoAcidIndel2AlignWithBandingemissionId[id] : _AminoAcidIndel2AlignWithBandingempty; }
const string& AminoAcidIndel2AlignWithBandingDPTable::getStateId(int id) { return id>=0 && id<_AminoAcidIndel2AlignWithBandingstateNum ? _AminoAcidIndel2AlignWithBandingstateId[id] : _AminoAcidIndel2AlignWithBandingempty; }
const string& AminoAcidIndel2AlignWithBandingDPTable::getOutputId(int id) { return id>=0 && id<_AminoAcidIndel2AlignWithBandingoutputNum ? _AminoAcidIndel2AlignWithBandingoutputId[id] : _AminoAcidIndel2AlignWithBandingempty; }
int AminoAcidIndel2AlignWithBandingDPTable::getId(const string& sId)
{
    static bool bInit = false;
    static map<string,int>* pmId;
    if (!bInit) {
        pmId = new map<string,int>();
        for (int i=0;i<_AminoAcidIndel2AlignWithBandingstateNum;i++) {
            (*pmId)[_AminoAcidIndel2AlignWithBandingstateId[i]] = i;         // add state identifiers
        }
        for (int i=0; i<_AminoAcidIndel2AlignWithBandingemitNum; i++) {
            (*pmId)[_AminoAcidIndel2AlignWithBandingemissionId[i]] = i;      // add emission identifiers
        }
        for (int i=0; i<_AminoAcidIndel2AlignWithBandingtransNum; i++) {  
            (*pmId)[_AminoAcidIndel2AlignWithBandingtransitionId[i]] = i;    // add transition identifiers
        }
        for (int i=0; i<_AminoAcidIndel2AlignWithBandingoutputNum; i++) {
            (*pmId)[_AminoAcidIndel2AlignWithBandingoutputId[i]] = i;        // finally, add output identifiers
        }
        bInit = true;
    }
    map<string,int>::iterator iter = pmId->find(sId);
    if (iter == pmId->end()) {
        if (sId == "_cleanup_") {
            delete pmId;
            } else {
            cout << "AminoAcidIndel2AlignWithBandingDPTable::getId: WARNING: identifier '" << sId << "' not found." << endl;
        }
        return -1;
    }
    return iter->second;
}


bfloat AminoAcidIndel2AlignWithBandingDPTable::getProb(const string sState ,int iPos0,int iPos1) const
{
    return getProb(getId(sState) ,iPos0,iPos1);
}


bfloat AminoAcidIndel2AlignWithBandingDPTable::getProb(int iState ,int iPos0,int iPos1) const
{
    const bfloat *CurStateMemoryaaIndel2Block1Secondary;
    const bfloat *CurStateMemoryaaIndel2Block2withbandingSecondary;
    const bfloat *CurStateMemoryaaIndel2Block3Secondary;
    static const int blockTable[] = {0, 1, 1, 1, 1, 1, 2};
    static const int stateTable[] = {0, 0, 1, 2, 3, 4, 0};
    switch (blockTable[iState]) {
        default:
        return 0.0;
        break;
        case 0:
        if ((iPos0+0>=0)&&(iPos0+0<=0)&&(iPos1+0>=0)&&(iPos1+0<=0)) {
            CurStateMemoryaaIndel2Block1Secondary = this->StateMemoryaaIndel2Block1.read();
            return CurStateMemoryaaIndel2Block1Secondary[stateTable[iState]];
        } 
        else { 
            return 0.0;
            
        }
        break;
        case 1:
        if ((iPos0+0>=0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=0)&&(iPos1+0<=iLen2+0)) {
            CurStateMemoryaaIndel2Block2withbandingSecondary = this->StateMemoryaaIndel2Block2withbanding.read((iPos0-(0))-(0), (iPos1-(0))-(0));
            return CurStateMemoryaaIndel2Block2withbandingSecondary[stateTable[iState]];
        } 
        else { 
            return 0.0;
            
        }
        break;
        case 2:
        if ((iPos0+0>=iLen1+0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=iLen2+0)&&(iPos1+0<=iLen2+0)) {
            CurStateMemoryaaIndel2Block3Secondary = this->StateMemoryaaIndel2Block3.read();
            return CurStateMemoryaaIndel2Block3Secondary[stateTable[iState]];
        } 
        else { 
            return 0.0;
            
        }
    } // switch
} // DPTable...::getProb(int,...)

const extern string _AminoAcidIndel2AlignWithBandingstateId[];
const extern string _AminoAcidIndel2AlignWithBandingemissionId[];
const extern string _AminoAcidIndel2AlignWithBandingtransitionId[];
const extern string _AminoAcidIndel2AlignWithBandingtransF[];
const extern string _AminoAcidIndel2AlignWithBandingtransT[];
const extern string _AminoAcidIndel2AlignWithBandingtransP[];
const extern string _AminoAcidIndel2AlignWithBandingtransE[];
const extern string _AminoAcidIndel2AlignWithBandingoutputId[];
const extern string _AminoAcidIndel2AlignWithBandingempty;
const extern int _AminoAcidIndel2AlignWithBandingstateNum;
const extern int _AminoAcidIndel2AlignWithBandingemitNum;
const extern int _AminoAcidIndel2AlignWithBandingtransNum;
const extern int _AminoAcidIndel2AlignWithBandingoutputNum;

AminoAcidIndel2AlignWithBandingFoldedDPTable::AminoAcidIndel2AlignWithBandingFoldedDPTable(int iLen1,int iLen2) : isInCharge(true), stateId(_AminoAcidIndel2AlignWithBandingstateId), emissionId(_AminoAcidIndel2AlignWithBandingemissionId), transitionId(_AminoAcidIndel2AlignWithBandingtransitionId), transitionFrom(_AminoAcidIndel2AlignWithBandingtransF), transitionTo(_AminoAcidIndel2AlignWithBandingtransT), transitionProb(_AminoAcidIndel2AlignWithBandingtransP), transitionEmit(_AminoAcidIndel2AlignWithBandingtransE), outputId(_AminoAcidIndel2AlignWithBandingoutputId) {
    // init code:
    this->iLen1 = iLen1;
    this->iLen2 = iLen2;
    StateMemoryaaIndel2Block2withbanding.allocate(1+iLen1, 1+iLen2);
    StateMemoryaaIndel2Block3.allocate();
    StateMemoryaaIndel2Block1.allocate();
}


AminoAcidIndel2AlignWithBandingFoldedDPTable::~AminoAcidIndel2AlignWithBandingFoldedDPTable() {
    if (!isInCharge) {
        // make sure data does not get deleted:
        StateMemoryaaIndel2Block2withbanding.absolve();
        StateMemoryaaIndel2Block3.absolve();
        StateMemoryaaIndel2Block1.absolve();
    } // if(!isInCharge)
} // destructor

const string& AminoAcidIndel2AlignWithBandingFoldedDPTable::getTransitionId(int id) { return id>=0 && id<_AminoAcidIndel2AlignWithBandingtransNum ? _AminoAcidIndel2AlignWithBandingtransitionId[id] : _AminoAcidIndel2AlignWithBandingempty; }
const string& AminoAcidIndel2AlignWithBandingFoldedDPTable::getEmissionId(int id) { return id>=0 && id<_AminoAcidIndel2AlignWithBandingemitNum ? _AminoAcidIndel2AlignWithBandingemissionId[id] : _AminoAcidIndel2AlignWithBandingempty; }
const string& AminoAcidIndel2AlignWithBandingFoldedDPTable::getStateId(int id) { return id>=0 && id<_AminoAcidIndel2AlignWithBandingstateNum ? _AminoAcidIndel2AlignWithBandingstateId[id] : _AminoAcidIndel2AlignWithBandingempty; }
const string& AminoAcidIndel2AlignWithBandingFoldedDPTable::getOutputId(int id) { return id>=0 && id<_AminoAcidIndel2AlignWithBandingoutputNum ? _AminoAcidIndel2AlignWithBandingoutputId[id] : _AminoAcidIndel2AlignWithBandingempty; }
int AminoAcidIndel2AlignWithBandingFoldedDPTable::getId(const string& sId)
{
    static bool bInit = false;
    static map<string,int>* pmId;
    if (!bInit) {
        pmId = new map<string,int>();
        for (int i=0;i<_AminoAcidIndel2AlignWithBandingstateNum;i++) {
            (*pmId)[_AminoAcidIndel2AlignWithBandingstateId[i]] = i;         // add state identifiers
        }
        for (int i=0; i<_AminoAcidIndel2AlignWithBandingemitNum; i++) {
            (*pmId)[_AminoAcidIndel2AlignWithBandingemissionId[i]] = i;      // add emission identifiers
        }
        for (int i=0; i<_AminoAcidIndel2AlignWithBandingtransNum; i++) {  
            (*pmId)[_AminoAcidIndel2AlignWithBandingtransitionId[i]] = i;    // add transition identifiers
        }
        for (int i=0; i<_AminoAcidIndel2AlignWithBandingoutputNum; i++) {
            (*pmId)[_AminoAcidIndel2AlignWithBandingoutputId[i]] = i;        // finally, add output identifiers
        }
        bInit = true;
    }
    map<string,int>::iterator iter = pmId->find(sId);
    if (iter == pmId->end()) {
        if (sId == "_cleanup_") {
            delete pmId;
            } else {
            cout << "AminoAcidIndel2AlignWithBandingFoldedDPTable::getId: WARNING: identifier '" << sId << "' not found." << endl;
        }
        return -1;
    }
    return iter->second;
}


bfloat AminoAcidIndel2AlignWithBandingFoldedDPTable::getProb(const string sState ,int iPos0,int iPos1) const
{
    return getProb(getId(sState) ,iPos0,iPos1);
}


bfloat AminoAcidIndel2AlignWithBandingFoldedDPTable::getProb(int iState ,int iPos0,int iPos1) const
{
    const bfloat *CurStateMemoryaaIndel2Block1Secondary;
    const bfloat *CurStateMemoryaaIndel2Block2withbandingSecondary;
    const bfloat *CurStateMemoryaaIndel2Block3Secondary;
    static const int blockTable[] = {0, 1, 1, 1, 1, 1, 2};
    static const int stateTable[] = {0, 0, 1, 2, 3, 4, 0};
    switch (blockTable[iState]) {
        default:
        return 0.0;
        break;
        case 0:
        if ((iPos0+0>=0)&&(iPos0+0<=0)&&(iPos1+0>=0)&&(iPos1+0<=0)) {
            CurStateMemoryaaIndel2Block1Secondary = this->StateMemoryaaIndel2Block1.read();
            return CurStateMemoryaaIndel2Block1Secondary[stateTable[iState]];
        } 
        else { 
            return 0.0;
            
        }
        break;
        case 1:
        if ((iPos0+0>=0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=0)&&(iPos1+0<=iLen2+0)) {
            CurStateMemoryaaIndel2Block2withbandingSecondary = this->StateMemoryaaIndel2Block2withbanding.read((iPos0-(0))-(0), (iPos1-(0))-(0));
            return CurStateMemoryaaIndel2Block2withbandingSecondary[stateTable[iState]];
        } 
        else { 
            return 0.0;
            
        }
        break;
        case 2:
        if ((iPos0+0>=iLen1+0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=iLen2+0)&&(iPos1+0<=iLen2+0)) {
            CurStateMemoryaaIndel2Block3Secondary = this->StateMemoryaaIndel2Block3.read();
            return CurStateMemoryaaIndel2Block3Secondary[stateTable[iState]];
        } 
        else { 
            return 0.0;
            
        }
    } // switch
} // DPTable...::getProb(int,...)

int AminoAcidIndel2AlignWithBandingBaumWelch::transitionIndex(string strId) const {
    map<const string,int>::const_iterator iter = mId.find(strId);
    if (iter == mId.end()) {
        cout << "AminoAcidIndel2AlignWithBandingBaumWelch::transitionIndex: WARNING: identifier '" << strId << "' not found." << endl;
        return -1;
    }
    return iter->second;
}


int AminoAcidIndel2AlignWithBandingBaumWelch::emissionIndex(string strId) const {
    map<const string,int>::const_iterator iter = mId.find(strId);
    if (iter == mId.end()) {
        cout << "AminoAcidIndel2AlignWithBandingBaumWelch::emissionIndex: WARNING: identifier '" << strId << "' not found." << endl;
        return -1;
    }
    return iter->second;
}


void AminoAcidIndel2AlignWithBandingBaumWelch::resetCounts() {
    static bool bInited = false;
    if (!bInited) {
        static const int aTemp[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22};
        for (int i=0; i<23; i++) {
            transitionIdentifier00[i] = aTemp[i];
            atransitionIdx[aTemp[i]] = i;
            mId[_AminoAcidIndel2AlignWithBandingtransitionId[aTemp[i]]] = i;
        }
    }
    for (int i=0; i<23; i++) {
        
        transitionBaumWelchCount00[i] = 0.0;
    }
    if (!bInited) {
        static const int aTemp[] = {2};
        for (int i=0; i<1; i++) {
            emissionIdentifier00[i] = aTemp[i];
            aemissionIdx[aTemp[i]] = i;
            mId[_AminoAcidIndel2AlignWithBandingemissionId[aTemp[i]]] = i;
        }
    }
    for (int i=0; i<1; i++) {
        
        emissionBaumWelchCount00[i] = 0.0;
    }
    if (!bInited) {
        static const int aTemp[] = {1};
        for (int i=0; i<1; i++) {
            emissionIdentifier01[i] = aTemp[i];
            aemissionIdx[aTemp[i]] = i;
            mId[_AminoAcidIndel2AlignWithBandingemissionId[aTemp[i]]] = i;
        }
    }
    for (int i=0; i<1; i++) {
        for(int v10=0;v10<20;v10++)
        emissionBaumWelchCount01[v10][i] = 0.0;
    }
    if (!bInited) {
        static const int aTemp[] = {3};
        for (int i=0; i<1; i++) {
            emissionIdentifier10[i] = aTemp[i];
            aemissionIdx[aTemp[i]] = i;
            mId[_AminoAcidIndel2AlignWithBandingemissionId[aTemp[i]]] = i;
        }
    }
    for (int i=0; i<1; i++) {
        for(int v00=0;v00<20;v00++)
        emissionBaumWelchCount10[v00][i] = 0.0;
    }
    if (!bInited) {
        static const int aTemp[] = {0};
        for (int i=0; i<1; i++) {
            emissionIdentifier11[i] = aTemp[i];
            aemissionIdx[aTemp[i]] = i;
            mId[_AminoAcidIndel2AlignWithBandingemissionId[aTemp[i]]] = i;
        }
    }
    for (int i=0; i<1; i++) {
        for(int v00=0;v00<20;v00++)for(int v10=0;v10<20;v10++)
        emissionBaumWelchCount11[v00][v10][i] = 0.0;
    }
    bInited = true;
};


int AminoAcidIndel2AlignWithBandingBaumWelch::transitionIdentifier00[];
int AminoAcidIndel2AlignWithBandingBaumWelch::emissionIdentifier00[];
int AminoAcidIndel2AlignWithBandingBaumWelch::emissionIdentifier01[];
int AminoAcidIndel2AlignWithBandingBaumWelch::emissionIdentifier10[];
int AminoAcidIndel2AlignWithBandingBaumWelch::emissionIdentifier11[];

void AminoAcidIndel2AlignWithBandingBaumWelch::scaleCounts(bfloat scale) {
    for (int i=0; i<23; i++) {
        
        transitionBaumWelchCount00[i] *= scale;
    }
    for (int i=0; i<1; i++) {
        
        emissionBaumWelchCount00[i] *= scale;
    }
    for (int i=0; i<1; i++) {
        for(int v10=0;v10<20;v10++)
        emissionBaumWelchCount01[v10][i] *= scale;
    }
    for (int i=0; i<1; i++) {
        for(int v00=0;v00<20;v00++)
        emissionBaumWelchCount10[v00][i] *= scale;
    }
    for (int i=0; i<1; i++) {
        for(int v00=0;v00<20;v00++)for(int v10=0;v10<20;v10++)
        emissionBaumWelchCount11[v00][v10][i] *= scale;
    }
}


map<const string,int> AminoAcidIndel2AlignWithBandingBaumWelch::mId;
int AminoAcidIndel2AlignWithBandingBaumWelch::atransitionIdx[];
int AminoAcidIndel2AlignWithBandingBaumWelch::aemissionIdx[];

const string _AminoAcidIndel2AlignstateId[] = {"start","delete2","delete1","insert1","match","insert2","end"};
const string _AminoAcidIndel2AlignemissionId[] = {"emit12","emit2","empty","emit1"};
const string _AminoAcidIndel2AligntransitionId[] = {"trSM","trSI1","trSD1","trSI2","trSD2","trMM","trMI1","trMD1","trMI2","trMD2","trME","trI1M","trI1I1","trI1E","trD1M","trD1D1","trD1E","trI2M","trI2I2","trI2E","trD2M","trD2D2","trD2E"};
const string _AminoAcidIndel2AligntransF[] = {"start","start","start","start","start","match","match","match","match","match","match","insert1","insert1","insert1","delete1","delete1","delete1","insert2","insert2","insert2","delete2","delete2","delete2"};
const string _AminoAcidIndel2AligntransT[] = {"match","insert1","delete1","insert2","delete2","match","insert1","delete1","insert2","delete2","end","match","insert1","end","match","delete1","end","match","insert2","end","match","delete2","end"};
const string _AminoAcidIndel2AligntransP[] = {"probSM","probSI1","probSD1","probSI2","probSD2","probMM","probMI1","probMD1","probMI2","probMD2","probME","probI1M","probI1I1","probI1E","probD1M","probD1D1","probD1E","probI2M","probI2I2","probI2E","probD2M","probD2D2","probD2E"};
const string _AminoAcidIndel2AligntransE[] = {"emit12","emit1","emit2","emit1","emit2","emit12","emit1","emit2","emit1","emit2","empty","emit12","emit1","empty","emit12","emit2","empty","emit12","emit1","empty","emit12","emit2","empty"};
const string _AminoAcidIndel2AlignoutputId[] = {"sequence1","sequence2"};
const string _AminoAcidIndel2Alignempty = "";
const int _AminoAcidIndel2AlignstateNum = 7;
const int _AminoAcidIndel2AlignemitNum = 4;
const int _AminoAcidIndel2AligntransNum = 23;
const int _AminoAcidIndel2AlignoutputNum = 2;




bfloat Forward(AminoAcidIndel2AlignDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT) {
    bfloat iTransition[23];
    bfloat *CurStateMemoryaaIndel2Block2To;
    const bfloat *CurStateMemoryaaIndel2Block1From;
    const bfloat *CurStateMemoryaaIndel2Block2From;
    bfloat *CurStateMemoryaaIndel2Block3To;
    const bfloat *CurStateMemoryaaIndel2Block3From;
    int iPrevSlowCoord;
    int iLen1 = iSequence1.size();   // The sequence lengths are not passed as parameters, but are
    int iLen2 = iSequence2.size();   // computed from the vector<char> itself
    
    // indexing for emission probs
    unsigned char iTranslate[256];
    for (int i=0; i<256; i++) {
        iTranslate[i]= 0;
    }
    iTranslate[(unsigned)'A'] = 0;   // It is important that this is in alphabetical order, to
    iTranslate[(unsigned)'a'] = 0;   // make the indices correspond to those used for Baum-Welch
    iTranslate[(unsigned)'C'] = 1;
    iTranslate[(unsigned)'c'] = 1;
    iTranslate[(unsigned)'D'] = 2;
    iTranslate[(unsigned)'d'] = 2;
    iTranslate[(unsigned)'E'] = 3;
    iTranslate[(unsigned)'e'] = 3;
    iTranslate[(unsigned)'F'] = 4;
    iTranslate[(unsigned)'f'] = 4;
    iTranslate[(unsigned)'G'] = 5;
    iTranslate[(unsigned)'g'] = 5;
    iTranslate[(unsigned)'H'] = 6;
    iTranslate[(unsigned)'h'] = 6;
    iTranslate[(unsigned)'I'] = 7;
    iTranslate[(unsigned)'i'] = 7;
    iTranslate[(unsigned)'K'] = 8;
    iTranslate[(unsigned)'k'] = 8;
    iTranslate[(unsigned)'L'] = 9;
    iTranslate[(unsigned)'l'] = 9;
    iTranslate[(unsigned)'M'] = 10;
    iTranslate[(unsigned)'m'] = 10;
    iTranslate[(unsigned)'N'] = 11;
    iTranslate[(unsigned)'n'] = 11;
    iTranslate[(unsigned)'P'] = 12;
    iTranslate[(unsigned)'p'] = 12;
    iTranslate[(unsigned)'Q'] = 13;
    iTranslate[(unsigned)'q'] = 13;
    iTranslate[(unsigned)'R'] = 14;
    iTranslate[(unsigned)'r'] = 14;
    iTranslate[(unsigned)'S'] = 15;
    iTranslate[(unsigned)'s'] = 15;
    iTranslate[(unsigned)'T'] = 16;
    iTranslate[(unsigned)'t'] = 16;
    iTranslate[(unsigned)'V'] = 17;
    iTranslate[(unsigned)'v'] = 17;
    iTranslate[(unsigned)'W'] = 18;
    iTranslate[(unsigned)'w'] = 18;
    iTranslate[(unsigned)'Y'] = 19;
    iTranslate[(unsigned)'y'] = 19;
    int iSymbol[2];
    if (false && iSymbol[0] == iSymbol[0]) {}   // avoid 'unused variable' warnings
    bfloat iEmission[1];
    /* temporary storage for ordinary reals */
    register double iTempResult[1];
    /* temporary storage for extended-exponent reals */
    register bfloat iTempProb[1];
    AminoAcidIndel2AlignDPTable dp(iLen1,iLen2);
    iTransition[0] = iT[0][1];
    
    iTransition[1] = iT[0][2];
    
    iTransition[2] = iT[0][3];
    
    iTransition[3] = iT[0][4];
    
    iTransition[4] = iT[0][5];
    
    iTransition[5] = iT[1][1];
    
    iTransition[6] = iT[1][2];
    
    iTransition[7] = iT[1][3];
    
    iTransition[8] = iT[1][4];
    
    iTransition[9] = iT[1][5];
    
    iTransition[10] = iT[1][6];
    
    iTransition[11] = iT[2][1];
    
    iTransition[12] = iT[2][2];
    
    iTransition[13] = iT[2][6];
    
    iTransition[14] = iT[3][1];
    
    iTransition[15] = iT[3][3];
    
    iTransition[16] = iT[3][6];
    
    iTransition[17] = iT[4][1];
    
    iTransition[18] = iT[4][4];
    
    iTransition[19] = iT[4][6];
    
    iTransition[20] = iT[5][1];
    
    iTransition[21] = iT[5][5];
    
    iTransition[22] = iT[5][6];
    dp.StateMemoryaaIndel2Block1.write()[0] = 1.0;
    dp.StateMemoryaaIndel2Block1.written();
    iPrevSlowCoord = -1;
    for (int iPos1=0; iPos1<iLen2+1; ++iPos1) {
        for (int iPos0=0; iPos0<iLen1+1; ++iPos0) {
            if ((iPos0+0<=0)&&(iPos1+0<=0)) {
            }
            if (1) {
                if ((iPos1+-1>=0)) {
                    iSymbol[0] = iSequence2[iPos1+-1];
                } 
                else { 
                    iSymbol[0] = 'A' /* dummy value */;
                    
                }
                if ((iPos0+-1>=0)) {
                    iSymbol[1] = iSequence1[iPos0+-1];
                } 
                else { 
                    iSymbol[1] = 'A' /* dummy value */;
                    
                }
                CurStateMemoryaaIndel2Block2To = dp.StateMemoryaaIndel2Block2.write((iPos0-(0))-(0), (iPos1-(0))-(0));
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+0<=0)&&(iPos1+-1>=0)&&(iPos1+-1<=0)) {
                    CurStateMemoryaaIndel2Block1From = dp.StateMemoryaaIndel2Block1.read();
                    CurStateMemoryaaIndel2Block2To[1] = ((iTransition[2])*(iEmission[0]))*CurStateMemoryaaIndel2Block1From[0];
                    CurStateMemoryaaIndel2Block2To[0] = ((iTransition[4])*(iEmission[0]))*CurStateMemoryaaIndel2Block1From[0];
                }
                if ((iPos1+-1>=0)) {
                    CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(0))-(0), (iPos1-(1))-(0));
                    CurStateMemoryaaIndel2Block2To[1] += ((iTransition[7])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
                    CurStateMemoryaaIndel2Block2To[1] += ((iTransition[15])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[1];
                    CurStateMemoryaaIndel2Block2To[0] += ((iTransition[9])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
                    CurStateMemoryaaIndel2Block2To[0] += ((iTransition[21])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[0];
                }
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+-1>=0)&&(iPos0+-1<=0)&&(iPos1+0<=0)) {
                    CurStateMemoryaaIndel2Block1From = dp.StateMemoryaaIndel2Block1.read();
                    CurStateMemoryaaIndel2Block2To[2] = ((iTransition[1])*(iEmission[0]))*CurStateMemoryaaIndel2Block1From[0];
                    CurStateMemoryaaIndel2Block2To[4] = ((iTransition[3])*(iEmission[0]))*CurStateMemoryaaIndel2Block1From[0];
                }
                if ((iPos0+-1>=0)) {
                    CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(1))-(0), (iPos1-(0))-(0));
                    CurStateMemoryaaIndel2Block2To[2] += ((iTransition[6])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
                    CurStateMemoryaaIndel2Block2To[2] += ((iTransition[12])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[2];
                    CurStateMemoryaaIndel2Block2To[4] += ((iTransition[8])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
                    CurStateMemoryaaIndel2Block2To[4] += ((iTransition[18])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[4];
                }
                iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+-1>=0)&&(iPos0+-1<=0)&&(iPos1+-1>=0)&&(iPos1+-1<=0)) {
                    CurStateMemoryaaIndel2Block1From = dp.StateMemoryaaIndel2Block1.read();
                    CurStateMemoryaaIndel2Block2To[3] = ((iTransition[0])*(iEmission[0]))*CurStateMemoryaaIndel2Block1From[0];
                }
                if ((iPos0+-1>=0)&&(iPos1+-1>=0)) {
                    CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(1))-(0), (iPos1-(1))-(0));
                    CurStateMemoryaaIndel2Block2To[3] += ((iTransition[5])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
                    CurStateMemoryaaIndel2Block2To[3] += ((iTransition[11])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[2];
                    CurStateMemoryaaIndel2Block2To[3] += ((iTransition[20])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[0];
                    CurStateMemoryaaIndel2Block2To[3] += ((iTransition[14])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[1];
                    CurStateMemoryaaIndel2Block2To[3] += ((iTransition[17])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[4];
                }
                dp.StateMemoryaaIndel2Block2.written();
            }
            if ((iPos0+0>=iLen1+0)&&(iPos1+0>=iLen2+0)) {
                CurStateMemoryaaIndel2Block3To = dp.StateMemoryaaIndel2Block3.write();
                iEmission[0] = 1.0;
                if (1) {
                    CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(0))-(0), (iPos1-(0))-(0));
                    CurStateMemoryaaIndel2Block3To[0] = ((iTransition[10])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
                    CurStateMemoryaaIndel2Block3To[0] += ((iTransition[13])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[2];
                    CurStateMemoryaaIndel2Block3To[0] += ((iTransition[22])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[0];
                    CurStateMemoryaaIndel2Block3To[0] += ((iTransition[16])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[1];
                    CurStateMemoryaaIndel2Block3To[0] += ((iTransition[19])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[4];
                }
                dp.StateMemoryaaIndel2Block3.written();
            }
            iPrevSlowCoord = iPos1;
        }
    }
    iPrevSlowCoord = -1;
    {
        int iPos1=iLen2+0;
        if (iPos1==iPos1) {} // avoid 'unused variable' warnings
        {
            int iPos0=iLen1+0;
            if (iPos0==iPos0) {} // avoid 'unused variable' warnings
            CurStateMemoryaaIndel2Block3From = dp.StateMemoryaaIndel2Block3.read();
            iTempProb[0] = CurStateMemoryaaIndel2Block3From[0];
        }
    }
    *ppOutTable = new AminoAcidIndel2AlignDPTable(dp);
    // make sure tables don't get deleted
    dp.isInCharge = false;
    return iTempProb[0];
};





bfloat BackwardBaumWelch(AminoAcidIndel2AlignBaumWelch& bw,AminoAcidIndel2AlignDPTable* pInTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT) {
    const bfloat *CurStateMemoryaaIndel2Block3Secondary;
    bfloat iTransition[23];
    bfloat *CurStateMemoryaaIndel2Block2To;
    const bfloat *CurStateMemoryaaIndel2Block2Secondary;
    const bfloat *CurStateMemoryaaIndel2Block2From;
    unsigned char alphaSymbolaminoacid[20] = {'A', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'Y'};
    unsigned char alphaIndexaminoacid[256];
    const bfloat *CurStateMemoryaaIndel2Block3From;
    bfloat *CurStateMemoryaaIndel2Block1To;
    const bfloat *CurStateMemoryaaIndel2Block1Secondary;
    const bfloat *CurStateMemoryaaIndel2Block1From;
    int iPrevSlowCoord;
    int iLen1 = iSequence1.size();   // The sequence lengths are not passed as parameters, but are
    int iLen2 = iSequence2.size();   // computed from the vector<char> itself
    
    // indexing for emission probs
    unsigned char iTranslate[256];
    for (int i=0; i<256; i++) {
        iTranslate[i]= 0;
    }
    iTranslate[(unsigned)'A'] = 0;   // It is important that this is in alphabetical order, to
    iTranslate[(unsigned)'a'] = 0;   // make the indices correspond to those used for Baum-Welch
    iTranslate[(unsigned)'C'] = 1;
    iTranslate[(unsigned)'c'] = 1;
    iTranslate[(unsigned)'D'] = 2;
    iTranslate[(unsigned)'d'] = 2;
    iTranslate[(unsigned)'E'] = 3;
    iTranslate[(unsigned)'e'] = 3;
    iTranslate[(unsigned)'F'] = 4;
    iTranslate[(unsigned)'f'] = 4;
    iTranslate[(unsigned)'G'] = 5;
    iTranslate[(unsigned)'g'] = 5;
    iTranslate[(unsigned)'H'] = 6;
    iTranslate[(unsigned)'h'] = 6;
    iTranslate[(unsigned)'I'] = 7;
    iTranslate[(unsigned)'i'] = 7;
    iTranslate[(unsigned)'K'] = 8;
    iTranslate[(unsigned)'k'] = 8;
    iTranslate[(unsigned)'L'] = 9;
    iTranslate[(unsigned)'l'] = 9;
    iTranslate[(unsigned)'M'] = 10;
    iTranslate[(unsigned)'m'] = 10;
    iTranslate[(unsigned)'N'] = 11;
    iTranslate[(unsigned)'n'] = 11;
    iTranslate[(unsigned)'P'] = 12;
    iTranslate[(unsigned)'p'] = 12;
    iTranslate[(unsigned)'Q'] = 13;
    iTranslate[(unsigned)'q'] = 13;
    iTranslate[(unsigned)'R'] = 14;
    iTranslate[(unsigned)'r'] = 14;
    iTranslate[(unsigned)'S'] = 15;
    iTranslate[(unsigned)'s'] = 15;
    iTranslate[(unsigned)'T'] = 16;
    iTranslate[(unsigned)'t'] = 16;
    iTranslate[(unsigned)'V'] = 17;
    iTranslate[(unsigned)'v'] = 17;
    iTranslate[(unsigned)'W'] = 18;
    iTranslate[(unsigned)'w'] = 18;
    iTranslate[(unsigned)'Y'] = 19;
    iTranslate[(unsigned)'y'] = 19;
    int iSymbol[2];
    if (false && iSymbol[0] == iSymbol[0]) {}   // avoid 'unused variable' warnings
    bfloat iEmission[1];
    /* temporary storage for ordinary reals */
    register double iTempResult[1];
    /* temporary storage for extended-exponent reals */
    register bfloat iTempProb[3];
    AminoAcidIndel2AlignFoldedDPTable dp(iLen1,2);
    AminoAcidIndel2AlignDPTable dp2(*pInTable);
    // make sure tables don't get deleted
    dp2.isInCharge = false;
    iTransition[0] = iT[0][1];
    
    iTransition[1] = iT[0][2];
    
    iTransition[2] = iT[0][3];
    
    iTransition[3] = iT[0][4];
    
    iTransition[4] = iT[0][5];
    
    iTransition[5] = iT[1][1];
    
    iTransition[6] = iT[1][2];
    
    iTransition[7] = iT[1][3];
    
    iTransition[8] = iT[1][4];
    
    iTransition[9] = iT[1][5];
    
    iTransition[10] = iT[1][6];
    
    iTransition[11] = iT[2][1];
    
    iTransition[12] = iT[2][2];
    
    iTransition[13] = iT[2][6];
    
    iTransition[14] = iT[3][1];
    
    iTransition[15] = iT[3][3];
    
    iTransition[16] = iT[3][6];
    
    iTransition[17] = iT[4][1];
    
    iTransition[18] = iT[4][4];
    
    iTransition[19] = iT[4][6];
    
    iTransition[20] = iT[5][1];
    
    iTransition[21] = iT[5][5];
    
    iTransition[22] = iT[5][6];
    for (int i=0; i<256; i++) {
        alphaIndexaminoacid[i]=0;
    }

//    for (int i=0; i<20; i++) {
//        alphaIndexaminoacid[alphaSymbolaminoacid[i]]=i;
//    }
    for (int i=0; i<20; i++) {
      alphaIndexaminoacid[tolower (alphaSymbolaminoacid[i])] = i;
      alphaIndexaminoacid[toupper (alphaSymbolaminoacid[i])] = i;
    }
    // treat lower and upper-case characters as equivalent during Baum-Welch
    // -- RKB

    dp.StateMemoryaaIndel2Block3.write()[0] = 1.0;
    dp.StateMemoryaaIndel2Block3.written();
    iPrevSlowCoord = -1;
    {
        int iPos1=iLen2+0;
        if (iPos1==iPos1) {} // avoid 'unused variable' warnings
        {
            int iPos0=iLen1+0;
            if (iPos0==iPos0) {} // avoid 'unused variable' warnings
            CurStateMemoryaaIndel2Block3Secondary = dp2.StateMemoryaaIndel2Block3.read();
            iTempProb[2] = CurStateMemoryaaIndel2Block3Secondary[0];
            bw.scaleCounts(iTempProb[2]);
        }
    }
    iPrevSlowCoord = -1;
    for (int iPos1=(iLen2+1)-1; iPos1>=0; --iPos1) {
        for (int iPos0=(iLen1+1)-1; iPos0>=0; --iPos0) {
            if (iPrevSlowCoord != -1 && iPrevSlowCoord != iPos1) {
                dp.StateMemoryaaIndel2Block2.clear(iPos1);
            }
            if ((iPos0+0>=iLen1+0)&&(iPos1+0>=iLen2+0)) {
            }
            if (1) {
                if ((iPos1+0<=iLen2+-1)) {
                    iSymbol[0] = iSequence2[iPos1+0];
                } 
                else { 
                    iSymbol[0] = 'A' /* dummy value */;
                    
                }
                if ((iPos0+0<=iLen1+-1)) {
                    iSymbol[1] = iSequence1[iPos0+0];
                } 
                else { 
                    iSymbol[1] = 'A' /* dummy value */;
                    
                }
                CurStateMemoryaaIndel2Block2To = dp.StateMemoryaaIndel2Block2.write((iPos0-(0))-(0), (iPos1-(0))-(0));
                CurStateMemoryaaIndel2Block2Secondary = dp2.StateMemoryaaIndel2Block2.read((iPos0-(0))-(0), (iPos1-(0))-(0));
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos1+1<=iLen2+0)) {
                    CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
                    CurStateMemoryaaIndel2Block2To[3] = iTempProb[1] = ((iTransition[7])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[1];
                    iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[3];
                    bw.transitionBaumWelchCount00[7] += iTempProb[1];
                    bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                    CurStateMemoryaaIndel2Block2To[3] += iTempProb[1] = ((iTransition[9])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[0];
                    iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[3];
                    bw.transitionBaumWelchCount00[9] += iTempProb[1];
                    bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                    CurStateMemoryaaIndel2Block2To[1] = iTempProb[1] = ((iTransition[15])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[1];
                    iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[1];
                    bw.transitionBaumWelchCount00[15] += iTempProb[1];
                    bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                    CurStateMemoryaaIndel2Block2To[0] = iTempProb[1] = ((iTransition[21])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[0];
                    iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[0];
                    bw.transitionBaumWelchCount00[21] += iTempProb[1];
                    bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                }
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+1<=iLen1+0)) {
                    CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
                    CurStateMemoryaaIndel2Block2To[2] = iTempProb[1] = ((iTransition[12])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[2];
                    iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[2];
                    bw.transitionBaumWelchCount00[12] += iTempProb[1];
                    bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
                    CurStateMemoryaaIndel2Block2To[3] += iTempProb[1] = ((iTransition[6])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[2];
                    iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[3];
                    bw.transitionBaumWelchCount00[6] += iTempProb[1];
                    bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
                    CurStateMemoryaaIndel2Block2To[3] += iTempProb[1] = ((iTransition[8])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[4];
                    iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[3];
                    bw.transitionBaumWelchCount00[8] += iTempProb[1];
                    bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
                    CurStateMemoryaaIndel2Block2To[4] = iTempProb[1] = ((iTransition[18])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[4];
                    iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[4];
                    bw.transitionBaumWelchCount00[18] += iTempProb[1];
                    bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
                }
                iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
                    CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
                    CurStateMemoryaaIndel2Block2To[2] += iTempProb[1] = ((iTransition[11])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
                    iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[2];
                    bw.transitionBaumWelchCount00[11] += iTempProb[1];
                    bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                    CurStateMemoryaaIndel2Block2To[1] += iTempProb[1] = ((iTransition[14])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
                    iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[1];
                    bw.transitionBaumWelchCount00[14] += iTempProb[1];
                    bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                    CurStateMemoryaaIndel2Block2To[4] += iTempProb[1] = ((iTransition[17])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
                    iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[4];
                    bw.transitionBaumWelchCount00[17] += iTempProb[1];
                    bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                    CurStateMemoryaaIndel2Block2To[0] += iTempProb[1] = ((iTransition[20])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
                    iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[0];
                    bw.transitionBaumWelchCount00[20] += iTempProb[1];
                    bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                    CurStateMemoryaaIndel2Block2To[3] += iTempProb[1] = ((iTransition[5])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
                    iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[3];
                    bw.transitionBaumWelchCount00[5] += iTempProb[1];
                    bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                }
                iEmission[0] = 1.0;
                if ((iPos0+0>=iLen1+0)&&(iPos1+0>=iLen2+0)) {
                    CurStateMemoryaaIndel2Block3From = dp.StateMemoryaaIndel2Block3.read();
                    CurStateMemoryaaIndel2Block2To[2] += iTempProb[1] = ((iTransition[13])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
                    iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[2];
                    bw.transitionBaumWelchCount00[13] += iTempProb[1];
                    bw.emissionBaumWelchCount00[0] += iTempProb[1];
                    CurStateMemoryaaIndel2Block2To[1] += iTempProb[1] = ((iTransition[16])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
                    iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[1];
                    bw.transitionBaumWelchCount00[16] += iTempProb[1];
                    bw.emissionBaumWelchCount00[0] += iTempProb[1];
                    CurStateMemoryaaIndel2Block2To[4] += iTempProb[1] = ((iTransition[19])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
                    iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[4];
                    bw.transitionBaumWelchCount00[19] += iTempProb[1];
                    bw.emissionBaumWelchCount00[0] += iTempProb[1];
                    CurStateMemoryaaIndel2Block2To[0] += iTempProb[1] = ((iTransition[22])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
                    iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[0];
                    bw.transitionBaumWelchCount00[22] += iTempProb[1];
                    bw.emissionBaumWelchCount00[0] += iTempProb[1];
                    CurStateMemoryaaIndel2Block2To[3] += iTempProb[1] = ((iTransition[10])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
                    iTempProb[1] *= CurStateMemoryaaIndel2Block2Secondary[3];
                    bw.transitionBaumWelchCount00[10] += iTempProb[1];
                    bw.emissionBaumWelchCount00[0] += iTempProb[1];
                }
                dp.StateMemoryaaIndel2Block2.written();
            }
            if ((iPos0+0<=0)&&(iPos1+0<=0)) {
                if ((iPos1+0<=iLen2+-1)) {
                    iSymbol[0] = iSequence2[iPos1+0];
                } 
                else { 
                    iSymbol[0] = 'A' /* dummy value */;
                    
                }
                if ((iPos0+0<=iLen1+-1)) {
                    iSymbol[1] = iSequence1[iPos0+0];
                } 
                else { 
                    iSymbol[1] = 'A' /* dummy value */;
                    
                }
                CurStateMemoryaaIndel2Block1To = dp.StateMemoryaaIndel2Block1.write();
                CurStateMemoryaaIndel2Block1Secondary = dp2.StateMemoryaaIndel2Block1.read();
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos1+1<=iLen2+0)) {
                    CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
                    CurStateMemoryaaIndel2Block1To[0] = iTempProb[1] = ((iTransition[2])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[1];
                    iTempProb[1] *= CurStateMemoryaaIndel2Block1Secondary[0];
                    bw.transitionBaumWelchCount00[2] += iTempProb[1];
                    bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                    CurStateMemoryaaIndel2Block1To[0] += iTempProb[1] = ((iTransition[4])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[0];
                    iTempProb[1] *= CurStateMemoryaaIndel2Block1Secondary[0];
                    bw.transitionBaumWelchCount00[4] += iTempProb[1];
                    bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                }
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+1<=iLen1+0)) {
                    CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
                    CurStateMemoryaaIndel2Block1To[0] += iTempProb[1] = ((iTransition[1])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[2];
                    iTempProb[1] *= CurStateMemoryaaIndel2Block1Secondary[0];
                    bw.transitionBaumWelchCount00[1] += iTempProb[1];
                    bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
                    CurStateMemoryaaIndel2Block1To[0] += iTempProb[1] = ((iTransition[3])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[4];
                    iTempProb[1] *= CurStateMemoryaaIndel2Block1Secondary[0];
                    bw.transitionBaumWelchCount00[3] += iTempProb[1];
                    bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
                }
                iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
                    CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
                    CurStateMemoryaaIndel2Block1To[0] += iTempProb[1] = ((iTransition[0])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
                    iTempProb[1] *= CurStateMemoryaaIndel2Block1Secondary[0];
                    bw.transitionBaumWelchCount00[0] += iTempProb[1];
                    bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                }
                dp.StateMemoryaaIndel2Block1.written();
            }
            iPrevSlowCoord = iPos1;
        }
    }
    bw.scaleCounts(1.0 / iTempProb[2]);
    iPrevSlowCoord = -1;
    {
        int iPos1=0;
        if (iPos1==iPos1) {} // avoid 'unused variable' warnings
        {
            int iPos0=0;
            if (iPos0==iPos0) {} // avoid 'unused variable' warnings
            CurStateMemoryaaIndel2Block1From = dp.StateMemoryaaIndel2Block1.read();
            iTempProb[0] = CurStateMemoryaaIndel2Block1From[0];
        }
    }
    return iTempProb[0];
};





bfloat Backward(AminoAcidIndel2AlignDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT) {
    bfloat iTransition[23];
    bfloat *CurStateMemoryaaIndel2Block2To;
    const bfloat *CurStateMemoryaaIndel2Block2From;
    const bfloat *CurStateMemoryaaIndel2Block3From;
    bfloat *CurStateMemoryaaIndel2Block1To;
    const bfloat *CurStateMemoryaaIndel2Block1From;
    int iPrevSlowCoord;
    int iLen1 = iSequence1.size();   // The sequence lengths are not passed as parameters, but are
    int iLen2 = iSequence2.size();   // computed from the vector<char> itself
    
    // indexing for emission probs
    unsigned char iTranslate[256];
    for (int i=0; i<256; i++) {
        iTranslate[i]= 0;
    }
    iTranslate[(unsigned)'A'] = 0;   // It is important that this is in alphabetical order, to
    iTranslate[(unsigned)'a'] = 0;   // make the indices correspond to those used for Baum-Welch
    iTranslate[(unsigned)'C'] = 1;
    iTranslate[(unsigned)'c'] = 1;
    iTranslate[(unsigned)'D'] = 2;
    iTranslate[(unsigned)'d'] = 2;
    iTranslate[(unsigned)'E'] = 3;
    iTranslate[(unsigned)'e'] = 3;
    iTranslate[(unsigned)'F'] = 4;
    iTranslate[(unsigned)'f'] = 4;
    iTranslate[(unsigned)'G'] = 5;
    iTranslate[(unsigned)'g'] = 5;
    iTranslate[(unsigned)'H'] = 6;
    iTranslate[(unsigned)'h'] = 6;
    iTranslate[(unsigned)'I'] = 7;
    iTranslate[(unsigned)'i'] = 7;
    iTranslate[(unsigned)'K'] = 8;
    iTranslate[(unsigned)'k'] = 8;
    iTranslate[(unsigned)'L'] = 9;
    iTranslate[(unsigned)'l'] = 9;
    iTranslate[(unsigned)'M'] = 10;
    iTranslate[(unsigned)'m'] = 10;
    iTranslate[(unsigned)'N'] = 11;
    iTranslate[(unsigned)'n'] = 11;
    iTranslate[(unsigned)'P'] = 12;
    iTranslate[(unsigned)'p'] = 12;
    iTranslate[(unsigned)'Q'] = 13;
    iTranslate[(unsigned)'q'] = 13;
    iTranslate[(unsigned)'R'] = 14;
    iTranslate[(unsigned)'r'] = 14;
    iTranslate[(unsigned)'S'] = 15;
    iTranslate[(unsigned)'s'] = 15;
    iTranslate[(unsigned)'T'] = 16;
    iTranslate[(unsigned)'t'] = 16;
    iTranslate[(unsigned)'V'] = 17;
    iTranslate[(unsigned)'v'] = 17;
    iTranslate[(unsigned)'W'] = 18;
    iTranslate[(unsigned)'w'] = 18;
    iTranslate[(unsigned)'Y'] = 19;
    iTranslate[(unsigned)'y'] = 19;
    int iSymbol[2];
    if (false && iSymbol[0] == iSymbol[0]) {}   // avoid 'unused variable' warnings
    bfloat iEmission[1];
    /* temporary storage for ordinary reals */
    register double iTempResult[1];
    /* temporary storage for extended-exponent reals */
    register bfloat iTempProb[1];
    AminoAcidIndel2AlignDPTable dp(iLen1,iLen2);
    iTransition[0] = iT[0][1];
    
    iTransition[1] = iT[0][2];
    
    iTransition[2] = iT[0][3];
    
    iTransition[3] = iT[0][4];
    
    iTransition[4] = iT[0][5];
    
    iTransition[5] = iT[1][1];
    
    iTransition[6] = iT[1][2];
    
    iTransition[7] = iT[1][3];
    
    iTransition[8] = iT[1][4];
    
    iTransition[9] = iT[1][5];
    
    iTransition[10] = iT[1][6];
    
    iTransition[11] = iT[2][1];
    
    iTransition[12] = iT[2][2];
    
    iTransition[13] = iT[2][6];
    
    iTransition[14] = iT[3][1];
    
    iTransition[15] = iT[3][3];
    
    iTransition[16] = iT[3][6];
    
    iTransition[17] = iT[4][1];
    
    iTransition[18] = iT[4][4];
    
    iTransition[19] = iT[4][6];
    
    iTransition[20] = iT[5][1];
    
    iTransition[21] = iT[5][5];
    
    iTransition[22] = iT[5][6];
    dp.StateMemoryaaIndel2Block3.write()[0] = 1.0;
    dp.StateMemoryaaIndel2Block3.written();
    iPrevSlowCoord = -1;
    for (int iPos1=(iLen2+1)-1; iPos1>=0; --iPos1) {
        for (int iPos0=(iLen1+1)-1; iPos0>=0; --iPos0) {
            if ((iPos0+0>=iLen1+0)&&(iPos1+0>=iLen2+0)) {
            }
            if (1) {
                if ((iPos1+0<=iLen2+-1)) {
                    iSymbol[0] = iSequence2[iPos1+0];
                } 
                else { 
                    iSymbol[0] = 'A' /* dummy value */;
                    
                }
                if ((iPos0+0<=iLen1+-1)) {
                    iSymbol[1] = iSequence1[iPos0+0];
                } 
                else { 
                    iSymbol[1] = 'A' /* dummy value */;
                    
                }
                CurStateMemoryaaIndel2Block2To = dp.StateMemoryaaIndel2Block2.write((iPos0-(0))-(0), (iPos1-(0))-(0));
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos1+1<=iLen2+0)) {
                    CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
                    CurStateMemoryaaIndel2Block2To[0] = ((iTransition[21])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[0];
                    CurStateMemoryaaIndel2Block2To[3] = ((iTransition[9])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[0];
                    CurStateMemoryaaIndel2Block2To[3] += ((iTransition[7])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[1];
                    CurStateMemoryaaIndel2Block2To[1] = ((iTransition[15])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[1];
                }
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+1<=iLen1+0)) {
                    CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
                    CurStateMemoryaaIndel2Block2To[2] = ((iTransition[12])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[2];
                    CurStateMemoryaaIndel2Block2To[3] += ((iTransition[6])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[2];
                    CurStateMemoryaaIndel2Block2To[3] += ((iTransition[8])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[4];
                    CurStateMemoryaaIndel2Block2To[4] = ((iTransition[18])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[4];
                }
                iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
                    CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
                    CurStateMemoryaaIndel2Block2To[2] += ((iTransition[11])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
                    CurStateMemoryaaIndel2Block2To[0] += ((iTransition[20])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
                    CurStateMemoryaaIndel2Block2To[3] += ((iTransition[5])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
                    CurStateMemoryaaIndel2Block2To[4] += ((iTransition[17])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
                    CurStateMemoryaaIndel2Block2To[1] += ((iTransition[14])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
                }
                iEmission[0] = 1.0;
                if ((iPos0+0>=iLen1+0)&&(iPos1+0>=iLen2+0)) {
                    CurStateMemoryaaIndel2Block3From = dp.StateMemoryaaIndel2Block3.read();
                    CurStateMemoryaaIndel2Block2To[2] += ((iTransition[13])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
                    CurStateMemoryaaIndel2Block2To[0] += ((iTransition[22])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
                    CurStateMemoryaaIndel2Block2To[3] += ((iTransition[10])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
                    CurStateMemoryaaIndel2Block2To[4] += ((iTransition[19])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
                    CurStateMemoryaaIndel2Block2To[1] += ((iTransition[16])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
                }
                dp.StateMemoryaaIndel2Block2.written();
            }
            if ((iPos0+0<=0)&&(iPos1+0<=0)) {
                if ((iPos1+0<=iLen2+-1)) {
                    iSymbol[0] = iSequence2[iPos1+0];
                } 
                else { 
                    iSymbol[0] = 'A' /* dummy value */;
                    
                }
                if ((iPos0+0<=iLen1+-1)) {
                    iSymbol[1] = iSequence1[iPos0+0];
                } 
                else { 
                    iSymbol[1] = 'A' /* dummy value */;
                    
                }
                CurStateMemoryaaIndel2Block1To = dp.StateMemoryaaIndel2Block1.write();
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos1+1<=iLen2+0)) {
                    CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
                    CurStateMemoryaaIndel2Block1To[0] = ((iTransition[4])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[0];
                    CurStateMemoryaaIndel2Block1To[0] += ((iTransition[2])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[1];
                }
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+1<=iLen1+0)) {
                    CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
                    CurStateMemoryaaIndel2Block1To[0] += ((iTransition[1])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[2];
                    CurStateMemoryaaIndel2Block1To[0] += ((iTransition[3])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[4];
                }
                iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
                    CurStateMemoryaaIndel2Block2From = dp.StateMemoryaaIndel2Block2.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
                    CurStateMemoryaaIndel2Block1To[0] += ((iTransition[0])*(iEmission[0]))*CurStateMemoryaaIndel2Block2From[3];
                }
                dp.StateMemoryaaIndel2Block1.written();
            }
            iPrevSlowCoord = iPos1;
        }
    }
    iPrevSlowCoord = -1;
    {
        int iPos1=0;
        if (iPos1==iPos1) {} // avoid 'unused variable' warnings
        {
            int iPos0=0;
            if (iPos0==iPos0) {} // avoid 'unused variable' warnings
            CurStateMemoryaaIndel2Block1From = dp.StateMemoryaaIndel2Block1.read();
            iTempProb[0] = CurStateMemoryaaIndel2Block1From[0];
        }
    }
    *ppOutTable = new AminoAcidIndel2AlignDPTable(dp);
    // make sure tables don't get deleted
    dp.isInCharge = false;
    return iTempProb[0];
};



const string _AminoAcidIndel2AlignWithBandingstateId[] = {"start","delete2","delete1","insert1","match","insert2","end"};
const string _AminoAcidIndel2AlignWithBandingemissionId[] = {"emit12","emit2","empty","emit1"};
const string _AminoAcidIndel2AlignWithBandingtransitionId[] = {"trSM","trSI1","trSD1","trSI2","trSD2","trMM","trMI1","trMD1","trMI2","trMD2","trME","trI1M","trI1I1","trI1E","trD1M","trD1D1","trD1E","trI2M","trI2I2","trI2E","trD2M","trD2D2","trD2E"};
const string _AminoAcidIndel2AlignWithBandingtransF[] = {"start","start","start","start","start","match","match","match","match","match","match","insert1","insert1","insert1","delete1","delete1","delete1","insert2","insert2","insert2","delete2","delete2","delete2"};
const string _AminoAcidIndel2AlignWithBandingtransT[] = {"match","insert1","delete1","insert2","delete2","match","insert1","delete1","insert2","delete2","end","match","insert1","end","match","delete1","end","match","insert2","end","match","delete2","end"};
const string _AminoAcidIndel2AlignWithBandingtransP[] = {"probSM","probSI1","probSD1","probSI2","probSD2","probMM","probMI1","probMD1","probMI2","probMD2","probME","probI1M","probI1I1","probI1E","probD1M","probD1D1","probD1E","probI2M","probI2I2","probI2E","probD2M","probD2D2","probD2E"};
const string _AminoAcidIndel2AlignWithBandingtransE[] = {"emit12","emit1","emit2","emit1","emit2","emit12","emit1","emit2","emit1","emit2","empty","emit12","emit1","empty","emit12","emit2","empty","emit12","emit1","empty","emit12","emit2","empty"};
const string _AminoAcidIndel2AlignWithBandingoutputId[] = {"sequence1","sequence2"};
const string _AminoAcidIndel2AlignWithBandingempty = "";
const int _AminoAcidIndel2AlignWithBandingstateNum = 7;
const int _AminoAcidIndel2AlignWithBandingemitNum = 4;
const int _AminoAcidIndel2AlignWithBandingtransNum = 23;
const int _AminoAcidIndel2AlignWithBandingoutputNum = 2;




bfloat ForwardBanding(AminoAcidIndel2AlignWithBandingDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT,int iWidth) {
    bfloat iTransition[23];
    bfloat *CurStateMemoryaaIndel2Block2withbandingTo;
    const bfloat *CurStateMemoryaaIndel2Block1From;
    const bfloat *CurStateMemoryaaIndel2Block2withbandingFrom;
    bfloat *CurStateMemoryaaIndel2Block3To;
    const bfloat *CurStateMemoryaaIndel2Block3From;
    int iPrevSlowCoord;
    int iLen1 = iSequence1.size();   // The sequence lengths are not passed as parameters, but are
    int iLen2 = iSequence2.size();   // computed from the vector<char> itself
    
    // indexing for emission probs
    unsigned char iTranslate[256];
    for (int i=0; i<256; i++) {
        iTranslate[i]= 0;
    }
    iTranslate[(unsigned)'A'] = 0;   // It is important that this is in alphabetical order, to
    iTranslate[(unsigned)'a'] = 0;   // make the indices correspond to those used for Baum-Welch
    iTranslate[(unsigned)'C'] = 1;
    iTranslate[(unsigned)'c'] = 1;
    iTranslate[(unsigned)'D'] = 2;
    iTranslate[(unsigned)'d'] = 2;
    iTranslate[(unsigned)'E'] = 3;
    iTranslate[(unsigned)'e'] = 3;
    iTranslate[(unsigned)'F'] = 4;
    iTranslate[(unsigned)'f'] = 4;
    iTranslate[(unsigned)'G'] = 5;
    iTranslate[(unsigned)'g'] = 5;
    iTranslate[(unsigned)'H'] = 6;
    iTranslate[(unsigned)'h'] = 6;
    iTranslate[(unsigned)'I'] = 7;
    iTranslate[(unsigned)'i'] = 7;
    iTranslate[(unsigned)'K'] = 8;
    iTranslate[(unsigned)'k'] = 8;
    iTranslate[(unsigned)'L'] = 9;
    iTranslate[(unsigned)'l'] = 9;
    iTranslate[(unsigned)'M'] = 10;
    iTranslate[(unsigned)'m'] = 10;
    iTranslate[(unsigned)'N'] = 11;
    iTranslate[(unsigned)'n'] = 11;
    iTranslate[(unsigned)'P'] = 12;
    iTranslate[(unsigned)'p'] = 12;
    iTranslate[(unsigned)'Q'] = 13;
    iTranslate[(unsigned)'q'] = 13;
    iTranslate[(unsigned)'R'] = 14;
    iTranslate[(unsigned)'r'] = 14;
    iTranslate[(unsigned)'S'] = 15;
    iTranslate[(unsigned)'s'] = 15;
    iTranslate[(unsigned)'T'] = 16;
    iTranslate[(unsigned)'t'] = 16;
    iTranslate[(unsigned)'V'] = 17;
    iTranslate[(unsigned)'v'] = 17;
    iTranslate[(unsigned)'W'] = 18;
    iTranslate[(unsigned)'w'] = 18;
    iTranslate[(unsigned)'Y'] = 19;
    iTranslate[(unsigned)'y'] = 19;
    MyBanding bandingInstance (iSequence1.size(), iSequence2.size(), iWidth);
    int iSymbol[2];
    if (false && iSymbol[0] == iSymbol[0]) {}   // avoid 'unused variable' warnings
    bfloat iEmission[1];
    /* temporary storage for ordinary reals */
    register double iTempResult[1];
    /* temporary storage for extended-exponent reals */
    register bfloat iTempProb[1];
    AminoAcidIndel2AlignWithBandingDPTable dp(iLen1,iLen2);
    iTransition[0] = iT[0][1];
    
    iTransition[1] = iT[0][2];
    
    iTransition[2] = iT[0][3];
    
    iTransition[3] = iT[0][4];
    
    iTransition[4] = iT[0][5];
    
    iTransition[5] = iT[1][1];
    
    iTransition[6] = iT[1][2];
    
    iTransition[7] = iT[1][3];
    
    iTransition[8] = iT[1][4];
    
    iTransition[9] = iT[1][5];
    
    iTransition[10] = iT[1][6];
    
    iTransition[11] = iT[2][1];
    
    iTransition[12] = iT[2][2];
    
    iTransition[13] = iT[2][6];
    
    iTransition[14] = iT[3][1];
    
    iTransition[15] = iT[3][3];
    
    iTransition[16] = iT[3][6];
    
    iTransition[17] = iT[4][1];
    
    iTransition[18] = iT[4][4];
    
    iTransition[19] = iT[4][6];
    
    iTransition[20] = iT[5][1];
    
    iTransition[21] = iT[5][5];
    
    iTransition[22] = iT[5][6];
    dp.StateMemoryaaIndel2Block1.write()[0] = 1.0;
    dp.StateMemoryaaIndel2Block1.written();
    iPrevSlowCoord = -1;
    {
        int iPos1=0;
        if (iPos1==iPos1) {} // avoid 'unused variable' warnings
        {
            int iPos0=0;
            if (iPos0==iPos0) {} // avoid 'unused variable' warnings
            if (1) {
            }
        }
    }
    iPrevSlowCoord = -1;
    {
        Banding<2>::Position& position = bandingInstance.forwardIterator();
        bool bLastSlowCoordInited = false;
        int iLastSlowCoord = -1;  
        do {
            if (bLastSlowCoordInited) {
                if (iLastSlowCoord > position[1]) {
                    cout << "WARNING: Banding (forward): Slowest coordinate should be nondecreasing.  Perhaps forgot to specify speed of output coordinates?" << endl;
                }
                } else {
                bLastSlowCoordInited = true;
            }
            iLastSlowCoord = position[1];
            if ((position[0]+0>=0)&&(position[0]+0<=iLen1+0)&&(position[1]+0>=0)&&(position[1]+0<=iLen2+0)) {
                if (1) {
                    if ((position[1]+-1>=0)) {
                        iSymbol[0] = iSequence2[position[1]+-1];
                    } 
                    else { 
                        iSymbol[0] = 'A' /* dummy value */;
                        
                    }
                    if ((position[0]+-1>=0)) {
                        iSymbol[1] = iSequence1[position[0]+-1];
                    } 
                    else { 
                        iSymbol[1] = 'A' /* dummy value */;
                        
                    }
                    CurStateMemoryaaIndel2Block2withbandingTo = dp.StateMemoryaaIndel2Block2withbanding.write((position[0]-(0))-(0), (position[1]-(0))-(0));
                    iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
                    iEmission[0] = iTempResult[0];
                    if ((position[0]+0<=0)&&(position[1]+-1>=0)&&(position[1]+-1<=0)) {
                        CurStateMemoryaaIndel2Block1From = dp.StateMemoryaaIndel2Block1.read();
                        CurStateMemoryaaIndel2Block2withbandingTo[0] = ((iTransition[4])*(iEmission[0]))*CurStateMemoryaaIndel2Block1From[0];
                        CurStateMemoryaaIndel2Block2withbandingTo[1] = ((iTransition[2])*(iEmission[0]))*CurStateMemoryaaIndel2Block1From[0];
                    }
                    if ((position[1]+-1>=0)) {
                        CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((position[0]-(0))-(0), (position[1]-(1))-(0));
                        CurStateMemoryaaIndel2Block2withbandingTo[0] += ((iTransition[9])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
                        CurStateMemoryaaIndel2Block2withbandingTo[0] += ((iTransition[21])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[0];
                        CurStateMemoryaaIndel2Block2withbandingTo[1] += ((iTransition[7])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
                        CurStateMemoryaaIndel2Block2withbandingTo[1] += ((iTransition[15])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[1];
                    }
                    iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
                    iEmission[0] = iTempResult[0];
                    if ((position[0]+-1>=0)&&(position[0]+-1<=0)&&(position[1]+0<=0)) {
                        CurStateMemoryaaIndel2Block1From = dp.StateMemoryaaIndel2Block1.read();
                        CurStateMemoryaaIndel2Block2withbandingTo[2] = ((iTransition[1])*(iEmission[0]))*CurStateMemoryaaIndel2Block1From[0];
                        CurStateMemoryaaIndel2Block2withbandingTo[4] = ((iTransition[3])*(iEmission[0]))*CurStateMemoryaaIndel2Block1From[0];
                    }
                    if ((position[0]+-1>=0)) {
                        CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((position[0]-(1))-(0), (position[1]-(0))-(0));
                        CurStateMemoryaaIndel2Block2withbandingTo[2] += ((iTransition[12])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[2];
                        CurStateMemoryaaIndel2Block2withbandingTo[2] += ((iTransition[6])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
                        CurStateMemoryaaIndel2Block2withbandingTo[4] += ((iTransition[8])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
                        CurStateMemoryaaIndel2Block2withbandingTo[4] += ((iTransition[18])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[4];
                    }
                    iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
                    iEmission[0] = iTempResult[0];
                    if ((position[0]+-1>=0)&&(position[0]+-1<=0)&&(position[1]+-1>=0)&&(position[1]+-1<=0)) {
                        CurStateMemoryaaIndel2Block1From = dp.StateMemoryaaIndel2Block1.read();
                        CurStateMemoryaaIndel2Block2withbandingTo[3] = ((iTransition[0])*(iEmission[0]))*CurStateMemoryaaIndel2Block1From[0];
                    }
                    if ((position[0]+-1>=0)&&(position[1]+-1>=0)) {
                        CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((position[0]-(1))-(0), (position[1]-(1))-(0));
                        CurStateMemoryaaIndel2Block2withbandingTo[3] += ((iTransition[11])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[2];
                        CurStateMemoryaaIndel2Block2withbandingTo[3] += ((iTransition[20])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[0];
                        CurStateMemoryaaIndel2Block2withbandingTo[3] += ((iTransition[17])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[4];
                        CurStateMemoryaaIndel2Block2withbandingTo[3] += ((iTransition[14])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[1];
                        CurStateMemoryaaIndel2Block2withbandingTo[3] += ((iTransition[5])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
                    }
                    dp.StateMemoryaaIndel2Block2withbanding.written();
                }
                iPrevSlowCoord = position[1];
            } 
            else { 
                bandingInstance.warning();
                
            }
        } while (bandingInstance.hasNextForward());
    }
    iPrevSlowCoord = -1;
    {
        int iPos1=iLen2+0;
        if (iPos1==iPos1) {} // avoid 'unused variable' warnings
        {
            int iPos0=iLen1+0;
            if (iPos0==iPos0) {} // avoid 'unused variable' warnings
            if (1) {
                CurStateMemoryaaIndel2Block3To = dp.StateMemoryaaIndel2Block3.write();
                iEmission[0] = 1.0;
                if (1) {
                    CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((iPos0-(0))-(0), (iPos1-(0))-(0));
                    CurStateMemoryaaIndel2Block3To[0] = ((iTransition[13])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[2];
                    CurStateMemoryaaIndel2Block3To[0] += ((iTransition[22])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[0];
                    CurStateMemoryaaIndel2Block3To[0] += ((iTransition[19])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[4];
                    CurStateMemoryaaIndel2Block3To[0] += ((iTransition[16])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[1];
                    CurStateMemoryaaIndel2Block3To[0] += ((iTransition[10])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
                }
                dp.StateMemoryaaIndel2Block3.written();
            }
            iPrevSlowCoord = iPos1;
        }
    }
    iPrevSlowCoord = -1;
    {
        int iPos1=iLen2+0;
        if (iPos1==iPos1) {} // avoid 'unused variable' warnings
        {
            int iPos0=iLen1+0;
            if (iPos0==iPos0) {} // avoid 'unused variable' warnings
            CurStateMemoryaaIndel2Block3From = dp.StateMemoryaaIndel2Block3.read();
            iTempProb[0] = CurStateMemoryaaIndel2Block3From[0];
        }
    }
    *ppOutTable = new AminoAcidIndel2AlignWithBandingDPTable(dp);
    // make sure tables don't get deleted
    dp.isInCharge = false;
    return iTempProb[0];
};





bfloat BackwardBaumWelchBanding(AminoAcidIndel2AlignWithBandingBaumWelch& bw,AminoAcidIndel2AlignWithBandingDPTable* pInTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT,int iWidth) {
    const bfloat *CurStateMemoryaaIndel2Block3Secondary;
    bfloat iTransition[23];
    bfloat *CurStateMemoryaaIndel2Block2withbandingTo;
    const bfloat *CurStateMemoryaaIndel2Block2withbandingSecondary;
    const bfloat *CurStateMemoryaaIndel2Block2withbandingFrom;
    unsigned char alphaSymbolaminoacid[20] = {'A', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'Y'};
    unsigned char alphaIndexaminoacid[256];
    const bfloat *CurStateMemoryaaIndel2Block3From;
    bfloat *CurStateMemoryaaIndel2Block1To;
    const bfloat *CurStateMemoryaaIndel2Block1Secondary;
    const bfloat *CurStateMemoryaaIndel2Block1From;
    int iPrevSlowCoord;
    int iLen1 = iSequence1.size();   // The sequence lengths are not passed as parameters, but are
    int iLen2 = iSequence2.size();   // computed from the vector<char> itself
    
    // indexing for emission probs
    unsigned char iTranslate[256];
    for (int i=0; i<256; i++) {
        iTranslate[i]= 0;
    }
    iTranslate[(unsigned)'A'] = 0;   // It is important that this is in alphabetical order, to
    iTranslate[(unsigned)'a'] = 0;   // make the indices correspond to those used for Baum-Welch
    iTranslate[(unsigned)'C'] = 1;
    iTranslate[(unsigned)'c'] = 1;
    iTranslate[(unsigned)'D'] = 2;
    iTranslate[(unsigned)'d'] = 2;
    iTranslate[(unsigned)'E'] = 3;
    iTranslate[(unsigned)'e'] = 3;
    iTranslate[(unsigned)'F'] = 4;
    iTranslate[(unsigned)'f'] = 4;
    iTranslate[(unsigned)'G'] = 5;
    iTranslate[(unsigned)'g'] = 5;
    iTranslate[(unsigned)'H'] = 6;
    iTranslate[(unsigned)'h'] = 6;
    iTranslate[(unsigned)'I'] = 7;
    iTranslate[(unsigned)'i'] = 7;
    iTranslate[(unsigned)'K'] = 8;
    iTranslate[(unsigned)'k'] = 8;
    iTranslate[(unsigned)'L'] = 9;
    iTranslate[(unsigned)'l'] = 9;
    iTranslate[(unsigned)'M'] = 10;
    iTranslate[(unsigned)'m'] = 10;
    iTranslate[(unsigned)'N'] = 11;
    iTranslate[(unsigned)'n'] = 11;
    iTranslate[(unsigned)'P'] = 12;
    iTranslate[(unsigned)'p'] = 12;
    iTranslate[(unsigned)'Q'] = 13;
    iTranslate[(unsigned)'q'] = 13;
    iTranslate[(unsigned)'R'] = 14;
    iTranslate[(unsigned)'r'] = 14;
    iTranslate[(unsigned)'S'] = 15;
    iTranslate[(unsigned)'s'] = 15;
    iTranslate[(unsigned)'T'] = 16;
    iTranslate[(unsigned)'t'] = 16;
    iTranslate[(unsigned)'V'] = 17;
    iTranslate[(unsigned)'v'] = 17;
    iTranslate[(unsigned)'W'] = 18;
    iTranslate[(unsigned)'w'] = 18;
    iTranslate[(unsigned)'Y'] = 19;
    iTranslate[(unsigned)'y'] = 19;
    MyBanding bandingInstance (iSequence1.size(), iSequence2.size(), iWidth);
    int iSymbol[2];
    if (false && iSymbol[0] == iSymbol[0]) {}   // avoid 'unused variable' warnings
    bfloat iEmission[1];
    /* temporary storage for ordinary reals */
    register double iTempResult[1];
    /* temporary storage for extended-exponent reals */
    register bfloat iTempProb[3];
    AminoAcidIndel2AlignWithBandingFoldedDPTable dp(iLen1,2);
    AminoAcidIndel2AlignWithBandingDPTable dp2(*pInTable);
    // make sure tables don't get deleted
    dp2.isInCharge = false;
    iTransition[0] = iT[0][1];
    
    iTransition[1] = iT[0][2];
    
    iTransition[2] = iT[0][3];
    
    iTransition[3] = iT[0][4];
    
    iTransition[4] = iT[0][5];
    
    iTransition[5] = iT[1][1];
    
    iTransition[6] = iT[1][2];
    
    iTransition[7] = iT[1][3];
    
    iTransition[8] = iT[1][4];
    
    iTransition[9] = iT[1][5];
    
    iTransition[10] = iT[1][6];
    
    iTransition[11] = iT[2][1];
    
    iTransition[12] = iT[2][2];
    
    iTransition[13] = iT[2][6];
    
    iTransition[14] = iT[3][1];
    
    iTransition[15] = iT[3][3];
    
    iTransition[16] = iT[3][6];
    
    iTransition[17] = iT[4][1];
    
    iTransition[18] = iT[4][4];
    
    iTransition[19] = iT[4][6];
    
    iTransition[20] = iT[5][1];
    
    iTransition[21] = iT[5][5];
    
    iTransition[22] = iT[5][6];
    for (int i=0; i<256; i++) {
        alphaIndexaminoacid[i]=0;
    }

//    for (int i=0; i<20; i++) {
//        alphaIndexaminoacid[alphaSymbolaminoacid[i]]=i;
//    }
    for (int i=0; i<20; i++) {
      alphaIndexaminoacid[tolower (alphaSymbolaminoacid[i])] = i;
      alphaIndexaminoacid[toupper (alphaSymbolaminoacid[i])] = i;
    }
    // treat lower and upper-case characters as equivalent during Baum-Welch
    // -- RKB

    dp.StateMemoryaaIndel2Block3.write()[0] = 1.0;
    dp.StateMemoryaaIndel2Block3.written();
    iPrevSlowCoord = -1;
    {
        int iPos1=iLen2+0;
        if (iPos1==iPos1) {} // avoid 'unused variable' warnings
        {
            int iPos0=iLen1+0;
            if (iPos0==iPos0) {} // avoid 'unused variable' warnings
            CurStateMemoryaaIndel2Block3Secondary = dp2.StateMemoryaaIndel2Block3.read();
            iTempProb[2] = CurStateMemoryaaIndel2Block3Secondary[0];
            bw.scaleCounts(iTempProb[2]);
        }
    }
    iPrevSlowCoord = -1;
    {
        int iPos1=iLen2+0;
        if (iPos1==iPos1) {} // avoid 'unused variable' warnings
        {
            int iPos0=iLen1+0;
            if (iPos0==iPos0) {} // avoid 'unused variable' warnings
            if (1) {
            }
        }
    }
    iPrevSlowCoord = -1;
    {
        Banding<2>::Position& position = bandingInstance.backwardIterator();
        int iCheckSlowCoordTraversal = -1;  
        do {
            if (iCheckSlowCoordTraversal != -1 && iCheckSlowCoordTraversal < position[1]) {
                cout << "WARNING: Banding (backward): Slowest coordinate be nonincreasing.  Perhaps forgot to specify speed of output coordinates?" << endl;
            }
            iCheckSlowCoordTraversal = position[1];
            if ((position[0]+0>=0)&&(position[0]+0<=iLen1+0)&&(position[1]+0>=0)&&(position[1]+0<=iLen2+0)) {
                if (iPrevSlowCoord != -1 && iPrevSlowCoord != position[1]) {
                    dp.StateMemoryaaIndel2Block2withbanding.clear(position[1]);
                }
                if (1) {
                    if ((position[1]+0<=iLen2+-1)) {
                        iSymbol[0] = iSequence2[position[1]+0];
                    } 
                    else { 
                        iSymbol[0] = 'A' /* dummy value */;
                        
                    }
                    if ((position[0]+0<=iLen1+-1)) {
                        iSymbol[1] = iSequence1[position[0]+0];
                    } 
                    else { 
                        iSymbol[1] = 'A' /* dummy value */;
                        
                    }
                    CurStateMemoryaaIndel2Block2withbandingTo = dp.StateMemoryaaIndel2Block2withbanding.write((position[0]-(0))-(0), (position[1]-(0))-(0));
                    CurStateMemoryaaIndel2Block2withbandingSecondary = dp2.StateMemoryaaIndel2Block2withbanding.read((position[0]-(0))-(0), (position[1]-(0))-(0));
                    iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
                    iEmission[0] = iTempResult[0];
                    if ((position[1]+1<=iLen2+0)) {
                        CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((position[0]-(0))-(0), (position[1]-(-1))-(0));
                        CurStateMemoryaaIndel2Block2withbandingTo[0] = iTempProb[1] = ((iTransition[21])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[0];
                        iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[0];
                        bw.transitionBaumWelchCount00[21] += iTempProb[1];
                        bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                        CurStateMemoryaaIndel2Block2withbandingTo[1] = iTempProb[1] = ((iTransition[15])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[1];
                        iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[1];
                        bw.transitionBaumWelchCount00[15] += iTempProb[1];
                        bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                        CurStateMemoryaaIndel2Block2withbandingTo[3] = iTempProb[1] = ((iTransition[7])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[1];
                        iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[3];
                        bw.transitionBaumWelchCount00[7] += iTempProb[1];
                        bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                        CurStateMemoryaaIndel2Block2withbandingTo[3] += iTempProb[1] = ((iTransition[9])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[0];
                        iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[3];
                        bw.transitionBaumWelchCount00[9] += iTempProb[1];
                        bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                    }
                    iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
                    iEmission[0] = iTempResult[0];
                    if ((position[0]+1<=iLen1+0)) {
                        CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((position[0]-(-1))-(0), (position[1]-(0))-(0));
                        CurStateMemoryaaIndel2Block2withbandingTo[4] = iTempProb[1] = ((iTransition[18])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[4];
                        iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[4];
                        bw.transitionBaumWelchCount00[18] += iTempProb[1];
                        bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
                        CurStateMemoryaaIndel2Block2withbandingTo[3] += iTempProb[1] = ((iTransition[6])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[2];
                        iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[3];
                        bw.transitionBaumWelchCount00[6] += iTempProb[1];
                        bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
                        CurStateMemoryaaIndel2Block2withbandingTo[3] += iTempProb[1] = ((iTransition[8])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[4];
                        iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[3];
                        bw.transitionBaumWelchCount00[8] += iTempProb[1];
                        bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
                        CurStateMemoryaaIndel2Block2withbandingTo[2] = iTempProb[1] = ((iTransition[12])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[2];
                        iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[2];
                        bw.transitionBaumWelchCount00[12] += iTempProb[1];
                        bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
                    }
                    iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
                    iEmission[0] = iTempResult[0];
                    if ((position[0]+1<=iLen1+0)&&(position[1]+1<=iLen2+0)) {
                        CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((position[0]-(-1))-(0), (position[1]-(-1))-(0));
                        CurStateMemoryaaIndel2Block2withbandingTo[3] += iTempProb[1] = ((iTransition[5])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
                        iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[3];
                        bw.transitionBaumWelchCount00[5] += iTempProb[1];
                        bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                        CurStateMemoryaaIndel2Block2withbandingTo[0] += iTempProb[1] = ((iTransition[20])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
                        iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[0];
                        bw.transitionBaumWelchCount00[20] += iTempProb[1];
                        bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                        CurStateMemoryaaIndel2Block2withbandingTo[1] += iTempProb[1] = ((iTransition[14])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
                        iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[1];
                        bw.transitionBaumWelchCount00[14] += iTempProb[1];
                        bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                        CurStateMemoryaaIndel2Block2withbandingTo[2] += iTempProb[1] = ((iTransition[11])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
                        iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[2];
                        bw.transitionBaumWelchCount00[11] += iTempProb[1];
                        bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                        CurStateMemoryaaIndel2Block2withbandingTo[4] += iTempProb[1] = ((iTransition[17])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
                        iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[4];
                        bw.transitionBaumWelchCount00[17] += iTempProb[1];
                        bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                    }
                    iEmission[0] = 1.0;
                    if ((position[0]+0>=iLen1+0)&&(position[1]+0>=iLen2+0)) {
                        CurStateMemoryaaIndel2Block3From = dp.StateMemoryaaIndel2Block3.read();
                        CurStateMemoryaaIndel2Block2withbandingTo[3] += iTempProb[1] = ((iTransition[10])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
                        iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[3];
                        bw.transitionBaumWelchCount00[10] += iTempProb[1];
                        bw.emissionBaumWelchCount00[0] += iTempProb[1];
                        CurStateMemoryaaIndel2Block2withbandingTo[0] += iTempProb[1] = ((iTransition[22])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
                        iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[0];
                        bw.transitionBaumWelchCount00[22] += iTempProb[1];
                        bw.emissionBaumWelchCount00[0] += iTempProb[1];
                        CurStateMemoryaaIndel2Block2withbandingTo[1] += iTempProb[1] = ((iTransition[16])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
                        iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[1];
                        bw.transitionBaumWelchCount00[16] += iTempProb[1];
                        bw.emissionBaumWelchCount00[0] += iTempProb[1];
                        CurStateMemoryaaIndel2Block2withbandingTo[2] += iTempProb[1] = ((iTransition[13])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
                        iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[2];
                        bw.transitionBaumWelchCount00[13] += iTempProb[1];
                        bw.emissionBaumWelchCount00[0] += iTempProb[1];
                        CurStateMemoryaaIndel2Block2withbandingTo[4] += iTempProb[1] = ((iTransition[19])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
                        iTempProb[1] *= CurStateMemoryaaIndel2Block2withbandingSecondary[4];
                        bw.transitionBaumWelchCount00[19] += iTempProb[1];
                        bw.emissionBaumWelchCount00[0] += iTempProb[1];
                    }
                    dp.StateMemoryaaIndel2Block2withbanding.written();
                }
                iPrevSlowCoord = position[1];
            } 
            else { 
                bandingInstance.warning();
                
            }
        } while (bandingInstance.hasNextBackward());
    }
    iPrevSlowCoord = -1;
    {
        int iPos1=0;
        if (iPos1==iPos1) {} // avoid 'unused variable' warnings
        {
            int iPos0=0;
            if (iPos0==iPos0) {} // avoid 'unused variable' warnings
            if (1) {
                if ((iPos1+0<=iLen2+-1)) {
                    iSymbol[0] = iSequence2[iPos1+0];
                } 
                else { 
                    iSymbol[0] = 'A' /* dummy value */;
                    
                }
                if ((iPos0+0<=iLen1+-1)) {
                    iSymbol[1] = iSequence1[iPos0+0];
                } 
                else { 
                    iSymbol[1] = 'A' /* dummy value */;
                    
                }
                CurStateMemoryaaIndel2Block1To = dp.StateMemoryaaIndel2Block1.write();
                CurStateMemoryaaIndel2Block1Secondary = dp2.StateMemoryaaIndel2Block1.read();
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos1+1<=iLen2+0)) {
                    CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
                    CurStateMemoryaaIndel2Block1To[0] = iTempProb[1] = ((iTransition[2])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[1];
                    iTempProb[1] *= CurStateMemoryaaIndel2Block1Secondary[0];
                    bw.transitionBaumWelchCount00[2] += iTempProb[1];
                    bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                    CurStateMemoryaaIndel2Block1To[0] += iTempProb[1] = ((iTransition[4])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[0];
                    iTempProb[1] *= CurStateMemoryaaIndel2Block1Secondary[0];
                    bw.transitionBaumWelchCount00[4] += iTempProb[1];
                    bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                }
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+1<=iLen1+0)) {
                    CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
                    CurStateMemoryaaIndel2Block1To[0] += iTempProb[1] = ((iTransition[1])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[2];
                    iTempProb[1] *= CurStateMemoryaaIndel2Block1Secondary[0];
                    bw.transitionBaumWelchCount00[1] += iTempProb[1];
                    bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
                    CurStateMemoryaaIndel2Block1To[0] += iTempProb[1] = ((iTransition[3])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[4];
                    iTempProb[1] *= CurStateMemoryaaIndel2Block1Secondary[0];
                    bw.transitionBaumWelchCount00[3] += iTempProb[1];
                    bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
                }
                iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
                    CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
                    CurStateMemoryaaIndel2Block1To[0] += iTempProb[1] = ((iTransition[0])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
                    iTempProb[1] *= CurStateMemoryaaIndel2Block1Secondary[0];
                    bw.transitionBaumWelchCount00[0] += iTempProb[1];
                    bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                }
                dp.StateMemoryaaIndel2Block1.written();
            }
            iPrevSlowCoord = iPos1;
        }
    }
    bw.scaleCounts(1.0 / iTempProb[2]);
    iPrevSlowCoord = -1;
    {
        int iPos1=0;
        if (iPos1==iPos1) {} // avoid 'unused variable' warnings
        {
            int iPos0=0;
            if (iPos0==iPos0) {} // avoid 'unused variable' warnings
            CurStateMemoryaaIndel2Block1From = dp.StateMemoryaaIndel2Block1.read();
            iTempProb[0] = CurStateMemoryaaIndel2Block1From[0];
        }
    }
    return iTempProb[0];
};





bfloat BackwardBanding(AminoAcidIndel2AlignWithBandingDPTable** ppOutTable,const std::string& iSequence1,const std::string& iSequence2,const vector<double>& iSingleDistribution,const vector<vector<double> >& iPairDistribution,const vector<vector<double> >& iT,int iWidth) {
    bfloat iTransition[23];
    bfloat *CurStateMemoryaaIndel2Block2withbandingTo;
    const bfloat *CurStateMemoryaaIndel2Block2withbandingFrom;
    const bfloat *CurStateMemoryaaIndel2Block3From;
    bfloat *CurStateMemoryaaIndel2Block1To;
    const bfloat *CurStateMemoryaaIndel2Block1From;
    int iPrevSlowCoord;
    int iLen1 = iSequence1.size();   // The sequence lengths are not passed as parameters, but are
    int iLen2 = iSequence2.size();   // computed from the vector<char> itself
    
    // indexing for emission probs
    unsigned char iTranslate[256];
    for (int i=0; i<256; i++) {
        iTranslate[i]= 0;
    }
    iTranslate[(unsigned)'A'] = 0;   // It is important that this is in alphabetical order, to
    iTranslate[(unsigned)'a'] = 0;   // make the indices correspond to those used for Baum-Welch
    iTranslate[(unsigned)'C'] = 1;
    iTranslate[(unsigned)'c'] = 1;
    iTranslate[(unsigned)'D'] = 2;
    iTranslate[(unsigned)'d'] = 2;
    iTranslate[(unsigned)'E'] = 3;
    iTranslate[(unsigned)'e'] = 3;
    iTranslate[(unsigned)'F'] = 4;
    iTranslate[(unsigned)'f'] = 4;
    iTranslate[(unsigned)'G'] = 5;
    iTranslate[(unsigned)'g'] = 5;
    iTranslate[(unsigned)'H'] = 6;
    iTranslate[(unsigned)'h'] = 6;
    iTranslate[(unsigned)'I'] = 7;
    iTranslate[(unsigned)'i'] = 7;
    iTranslate[(unsigned)'K'] = 8;
    iTranslate[(unsigned)'k'] = 8;
    iTranslate[(unsigned)'L'] = 9;
    iTranslate[(unsigned)'l'] = 9;
    iTranslate[(unsigned)'M'] = 10;
    iTranslate[(unsigned)'m'] = 10;
    iTranslate[(unsigned)'N'] = 11;
    iTranslate[(unsigned)'n'] = 11;
    iTranslate[(unsigned)'P'] = 12;
    iTranslate[(unsigned)'p'] = 12;
    iTranslate[(unsigned)'Q'] = 13;
    iTranslate[(unsigned)'q'] = 13;
    iTranslate[(unsigned)'R'] = 14;
    iTranslate[(unsigned)'r'] = 14;
    iTranslate[(unsigned)'S'] = 15;
    iTranslate[(unsigned)'s'] = 15;
    iTranslate[(unsigned)'T'] = 16;
    iTranslate[(unsigned)'t'] = 16;
    iTranslate[(unsigned)'V'] = 17;
    iTranslate[(unsigned)'v'] = 17;
    iTranslate[(unsigned)'W'] = 18;
    iTranslate[(unsigned)'w'] = 18;
    iTranslate[(unsigned)'Y'] = 19;
    iTranslate[(unsigned)'y'] = 19;
    MyBanding bandingInstance (iSequence1.size(), iSequence2.size(), iWidth);
    int iSymbol[2];
    if (false && iSymbol[0] == iSymbol[0]) {}   // avoid 'unused variable' warnings
    bfloat iEmission[1];
    /* temporary storage for ordinary reals */
    register double iTempResult[1];
    /* temporary storage for extended-exponent reals */
    register bfloat iTempProb[1];
    AminoAcidIndel2AlignWithBandingDPTable dp(iLen1,iLen2);
    iTransition[0] = iT[0][1];
    
    iTransition[1] = iT[0][2];
    
    iTransition[2] = iT[0][3];
    
    iTransition[3] = iT[0][4];
    
    iTransition[4] = iT[0][5];
    
    iTransition[5] = iT[1][1];
    
    iTransition[6] = iT[1][2];
    
    iTransition[7] = iT[1][3];
    
    iTransition[8] = iT[1][4];
    
    iTransition[9] = iT[1][5];
    
    iTransition[10] = iT[1][6];
    
    iTransition[11] = iT[2][1];
    
    iTransition[12] = iT[2][2];
    
    iTransition[13] = iT[2][6];
    
    iTransition[14] = iT[3][1];
    
    iTransition[15] = iT[3][3];
    
    iTransition[16] = iT[3][6];
    
    iTransition[17] = iT[4][1];
    
    iTransition[18] = iT[4][4];
    
    iTransition[19] = iT[4][6];
    
    iTransition[20] = iT[5][1];
    
    iTransition[21] = iT[5][5];
    
    iTransition[22] = iT[5][6];
    dp.StateMemoryaaIndel2Block3.write()[0] = 1.0;
    dp.StateMemoryaaIndel2Block3.written();
    iPrevSlowCoord = -1;
    {
        int iPos1=iLen2+0;
        if (iPos1==iPos1) {} // avoid 'unused variable' warnings
        {
            int iPos0=iLen1+0;
            if (iPos0==iPos0) {} // avoid 'unused variable' warnings
            if (1) {
            }
        }
    }
    iPrevSlowCoord = -1;
    {
        Banding<2>::Position& position = bandingInstance.backwardIterator();
        int iCheckSlowCoordTraversal = -1;  
        do {
            if (iCheckSlowCoordTraversal != -1 && iCheckSlowCoordTraversal < position[1]) {
                cout << "WARNING: Banding (backward): Slowest coordinate be nonincreasing.  Perhaps forgot to specify speed of output coordinates?" << endl;
            }
            iCheckSlowCoordTraversal = position[1];
            if ((position[0]+0>=0)&&(position[0]+0<=iLen1+0)&&(position[1]+0>=0)&&(position[1]+0<=iLen2+0)) {
                if (1) {
                    if ((position[1]+0<=iLen2+-1)) {
                        iSymbol[0] = iSequence2[position[1]+0];
                    } 
                    else { 
                        iSymbol[0] = 'A' /* dummy value */;
                        
                    }
                    if ((position[0]+0<=iLen1+-1)) {
                        iSymbol[1] = iSequence1[position[0]+0];
                    } 
                    else { 
                        iSymbol[1] = 'A' /* dummy value */;
                        
                    }
                    CurStateMemoryaaIndel2Block2withbandingTo = dp.StateMemoryaaIndel2Block2withbanding.write((position[0]-(0))-(0), (position[1]-(0))-(0));
                    iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
                    iEmission[0] = iTempResult[0];
                    if ((position[1]+1<=iLen2+0)) {
                        CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((position[0]-(0))-(0), (position[1]-(-1))-(0));
                        CurStateMemoryaaIndel2Block2withbandingTo[3] = ((iTransition[9])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[0];
                        CurStateMemoryaaIndel2Block2withbandingTo[3] += ((iTransition[7])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[1];
                        CurStateMemoryaaIndel2Block2withbandingTo[0] = ((iTransition[21])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[0];
                        CurStateMemoryaaIndel2Block2withbandingTo[1] = ((iTransition[15])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[1];
                    }
                    iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
                    iEmission[0] = iTempResult[0];
                    if ((position[0]+1<=iLen1+0)) {
                        CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((position[0]-(-1))-(0), (position[1]-(0))-(0));
                        CurStateMemoryaaIndel2Block2withbandingTo[3] += ((iTransition[6])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[2];
                        CurStateMemoryaaIndel2Block2withbandingTo[3] += ((iTransition[8])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[4];
                        CurStateMemoryaaIndel2Block2withbandingTo[2] = ((iTransition[12])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[2];
                        CurStateMemoryaaIndel2Block2withbandingTo[4] = ((iTransition[18])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[4];
                    }
                    iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
                    iEmission[0] = iTempResult[0];
                    if ((position[0]+1<=iLen1+0)&&(position[1]+1<=iLen2+0)) {
                        CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((position[0]-(-1))-(0), (position[1]-(-1))-(0));
                        CurStateMemoryaaIndel2Block2withbandingTo[3] += ((iTransition[5])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
                        CurStateMemoryaaIndel2Block2withbandingTo[0] += ((iTransition[20])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
                        CurStateMemoryaaIndel2Block2withbandingTo[2] += ((iTransition[11])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
                        CurStateMemoryaaIndel2Block2withbandingTo[1] += ((iTransition[14])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
                        CurStateMemoryaaIndel2Block2withbandingTo[4] += ((iTransition[17])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
                    }
                    iEmission[0] = 1.0;
                    if ((position[0]+0>=iLen1+0)&&(position[1]+0>=iLen2+0)) {
                        CurStateMemoryaaIndel2Block3From = dp.StateMemoryaaIndel2Block3.read();
                        CurStateMemoryaaIndel2Block2withbandingTo[3] += ((iTransition[10])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
                        CurStateMemoryaaIndel2Block2withbandingTo[0] += ((iTransition[22])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
                        CurStateMemoryaaIndel2Block2withbandingTo[2] += ((iTransition[13])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
                        CurStateMemoryaaIndel2Block2withbandingTo[1] += ((iTransition[16])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
                        CurStateMemoryaaIndel2Block2withbandingTo[4] += ((iTransition[19])*(iEmission[0]))*CurStateMemoryaaIndel2Block3From[0];
                    }
                    dp.StateMemoryaaIndel2Block2withbanding.written();
                }
                iPrevSlowCoord = position[1];
            } 
            else { 
                bandingInstance.warning();
                
            }
        } while (bandingInstance.hasNextBackward());
    }
    iPrevSlowCoord = -1;
    {
        int iPos1=0;
        if (iPos1==iPos1) {} // avoid 'unused variable' warnings
        {
            int iPos0=0;
            if (iPos0==iPos0) {} // avoid 'unused variable' warnings
            if (1) {
                if ((iPos1+0<=iLen2+-1)) {
                    iSymbol[0] = iSequence2[iPos1+0];
                } 
                else { 
                    iSymbol[0] = 'A' /* dummy value */;
                    
                }
                if ((iPos0+0<=iLen1+-1)) {
                    iSymbol[1] = iSequence1[iPos0+0];
                } 
                else { 
                    iSymbol[1] = 'A' /* dummy value */;
                    
                }
                CurStateMemoryaaIndel2Block1To = dp.StateMemoryaaIndel2Block1.write();
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos1+1<=iLen2+0)) {
                    CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
                    CurStateMemoryaaIndel2Block1To[0] = ((iTransition[4])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[0];
                    CurStateMemoryaaIndel2Block1To[0] += ((iTransition[2])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[1];
                }
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+1<=iLen1+0)) {
                    CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
                    CurStateMemoryaaIndel2Block1To[0] += ((iTransition[1])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[2];
                    CurStateMemoryaaIndel2Block1To[0] += ((iTransition[3])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[4];
                }
                iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
                    CurStateMemoryaaIndel2Block2withbandingFrom = dp.StateMemoryaaIndel2Block2withbanding.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
                    CurStateMemoryaaIndel2Block1To[0] += ((iTransition[0])*(iEmission[0]))*CurStateMemoryaaIndel2Block2withbandingFrom[3];
                }
                dp.StateMemoryaaIndel2Block1.written();
            }
            iPrevSlowCoord = iPos1;
        }
    }
    iPrevSlowCoord = -1;
    {
        int iPos1=0;
        if (iPos1==iPos1) {} // avoid 'unused variable' warnings
        {
            int iPos0=0;
            if (iPos0==iPos0) {} // avoid 'unused variable' warnings
            CurStateMemoryaaIndel2Block1From = dp.StateMemoryaaIndel2Block1.read();
            iTempProb[0] = CurStateMemoryaaIndel2Block1From[0];
        }
    }
    *ppOutTable = new AminoAcidIndel2AlignWithBandingDPTable(dp);
    // make sure tables don't get deleted
    dp.isInCharge = false;
    return iTempProb[0];
};



/* --- end of HMMoC-generated file --- */
