/* Code generated by HMMoC version 1.3, Copyright (C) 2006 Gerton Lunter */
/* Generated from file aminoacid.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 "aminoaciddp.h"

#include "mybanding.h"

const extern string _AminoAcidAlignstateId[];
const extern string _AminoAcidAlignemissionId[];
const extern string _AminoAcidAligntransitionId[];
const extern string _AminoAcidAligntransF[];
const extern string _AminoAcidAligntransT[];
const extern string _AminoAcidAligntransP[];
const extern string _AminoAcidAligntransE[];
const extern string _AminoAcidAlignoutputId[];
const extern string _AminoAcidAlignempty;
const extern int _AminoAcidAlignstateNum;
const extern int _AminoAcidAlignemitNum;
const extern int _AminoAcidAligntransNum;
const extern int _AminoAcidAlignoutputNum;

AminoAcidAlignDPTable::AminoAcidAlignDPTable(int iLen1,int iLen2) : isInCharge(true), stateId(_AminoAcidAlignstateId), emissionId(_AminoAcidAlignemissionId), transitionId(_AminoAcidAligntransitionId), transitionFrom(_AminoAcidAligntransF), transitionTo(_AminoAcidAligntransT), transitionProb(_AminoAcidAligntransP), transitionEmit(_AminoAcidAligntransE), outputId(_AminoAcidAlignoutputId) {
    // init code:
    this->iLen1 = iLen1;
    this->iLen2 = iLen2;
    StateMemoryaaBlock2.allocate(1+iLen1, 1+iLen2);
    StateMemoryaaBlock1.allocate();
    StateMemoryaaBlock3.allocate();
}


AminoAcidAlignDPTable::~AminoAcidAlignDPTable() {
    if (!isInCharge) {
        // make sure data does not get deleted:
        StateMemoryaaBlock2.absolve();
        StateMemoryaaBlock1.absolve();
        StateMemoryaaBlock3.absolve();
    } // if(!isInCharge)
} // destructor

const string& AminoAcidAlignDPTable::getTransitionId(int id) { return id>=0 && id<_AminoAcidAligntransNum ? _AminoAcidAligntransitionId[id] : _AminoAcidAlignempty; }
const string& AminoAcidAlignDPTable::getEmissionId(int id) { return id>=0 && id<_AminoAcidAlignemitNum ? _AminoAcidAlignemissionId[id] : _AminoAcidAlignempty; }
const string& AminoAcidAlignDPTable::getStateId(int id) { return id>=0 && id<_AminoAcidAlignstateNum ? _AminoAcidAlignstateId[id] : _AminoAcidAlignempty; }
const string& AminoAcidAlignDPTable::getOutputId(int id) { return id>=0 && id<_AminoAcidAlignoutputNum ? _AminoAcidAlignoutputId[id] : _AminoAcidAlignempty; }
int AminoAcidAlignDPTable::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<_AminoAcidAlignstateNum;i++) {
            (*pmId)[_AminoAcidAlignstateId[i]] = i;         // add state identifiers
        }
        for (int i=0; i<_AminoAcidAlignemitNum; i++) {
            (*pmId)[_AminoAcidAlignemissionId[i]] = i;      // add emission identifiers
        }
        for (int i=0; i<_AminoAcidAligntransNum; i++) {  
            (*pmId)[_AminoAcidAligntransitionId[i]] = i;    // add transition identifiers
        }
        for (int i=0; i<_AminoAcidAlignoutputNum; i++) {
            (*pmId)[_AminoAcidAlignoutputId[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 << "AminoAcidAlignDPTable::getId: WARNING: identifier '" << sId << "' not found." << endl;
        }
        return -1;
    }
    return iter->second;
}


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


bfloat AminoAcidAlignDPTable::getProb(int iState ,int iPos0,int iPos1) const
{
    const bfloat *CurStateMemoryaaBlock1Secondary;
    const bfloat *CurStateMemoryaaBlock2Secondary;
    const bfloat *CurStateMemoryaaBlock3Secondary;
    static const int blockTable[] = {0, 1, 1, 1, 2};
    static const int stateTable[] = {0, 0, 1, 2, 0};
    switch (blockTable[iState]) {
        default:
        return 0.0;
        break;
        case 0:
        if ((iPos0+0>=0)&&(iPos0+0<=0)&&(iPos1+0>=0)&&(iPos1+0<=0)) {
            CurStateMemoryaaBlock1Secondary = this->StateMemoryaaBlock1.read();
            return CurStateMemoryaaBlock1Secondary[stateTable[iState]];
        } 
        else { 
            return 0.0;
            
        }
        break;
        case 1:
        if ((iPos0+0>=0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=0)&&(iPos1+0<=iLen2+0)) {
            CurStateMemoryaaBlock2Secondary = this->StateMemoryaaBlock2.read((iPos0-(0))-(0), (iPos1-(0))-(0));
            return CurStateMemoryaaBlock2Secondary[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)) {
            CurStateMemoryaaBlock3Secondary = this->StateMemoryaaBlock3.read();
            return CurStateMemoryaaBlock3Secondary[stateTable[iState]];
        } 
        else { 
            return 0.0;
            
        }
    } // switch
} // DPTable...::getProb(int,...)

const extern string _AminoAcidAlignstateId[];
const extern string _AminoAcidAlignemissionId[];
const extern string _AminoAcidAligntransitionId[];
const extern string _AminoAcidAligntransF[];
const extern string _AminoAcidAligntransT[];
const extern string _AminoAcidAligntransP[];
const extern string _AminoAcidAligntransE[];
const extern string _AminoAcidAlignoutputId[];
const extern string _AminoAcidAlignempty;
const extern int _AminoAcidAlignstateNum;
const extern int _AminoAcidAlignemitNum;
const extern int _AminoAcidAligntransNum;
const extern int _AminoAcidAlignoutputNum;

AminoAcidAlignFoldedDPTable::AminoAcidAlignFoldedDPTable(int iLen1,int iLen2) : isInCharge(true), stateId(_AminoAcidAlignstateId), emissionId(_AminoAcidAlignemissionId), transitionId(_AminoAcidAligntransitionId), transitionFrom(_AminoAcidAligntransF), transitionTo(_AminoAcidAligntransT), transitionProb(_AminoAcidAligntransP), transitionEmit(_AminoAcidAligntransE), outputId(_AminoAcidAlignoutputId) {
    // init code:
    this->iLen1 = iLen1;
    this->iLen2 = iLen2;
    StateMemoryaaBlock2.allocate(1+iLen1, 1+iLen2);
    StateMemoryaaBlock3.allocate();
    StateMemoryaaBlock1.allocate();
}


AminoAcidAlignFoldedDPTable::~AminoAcidAlignFoldedDPTable() {
    if (!isInCharge) {
        // make sure data does not get deleted:
        StateMemoryaaBlock2.absolve();
        StateMemoryaaBlock3.absolve();
        StateMemoryaaBlock1.absolve();
    } // if(!isInCharge)
} // destructor

const string& AminoAcidAlignFoldedDPTable::getTransitionId(int id) { return id>=0 && id<_AminoAcidAligntransNum ? _AminoAcidAligntransitionId[id] : _AminoAcidAlignempty; }
const string& AminoAcidAlignFoldedDPTable::getEmissionId(int id) { return id>=0 && id<_AminoAcidAlignemitNum ? _AminoAcidAlignemissionId[id] : _AminoAcidAlignempty; }
const string& AminoAcidAlignFoldedDPTable::getStateId(int id) { return id>=0 && id<_AminoAcidAlignstateNum ? _AminoAcidAlignstateId[id] : _AminoAcidAlignempty; }
const string& AminoAcidAlignFoldedDPTable::getOutputId(int id) { return id>=0 && id<_AminoAcidAlignoutputNum ? _AminoAcidAlignoutputId[id] : _AminoAcidAlignempty; }
int AminoAcidAlignFoldedDPTable::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<_AminoAcidAlignstateNum;i++) {
            (*pmId)[_AminoAcidAlignstateId[i]] = i;         // add state identifiers
        }
        for (int i=0; i<_AminoAcidAlignemitNum; i++) {
            (*pmId)[_AminoAcidAlignemissionId[i]] = i;      // add emission identifiers
        }
        for (int i=0; i<_AminoAcidAligntransNum; i++) {  
            (*pmId)[_AminoAcidAligntransitionId[i]] = i;    // add transition identifiers
        }
        for (int i=0; i<_AminoAcidAlignoutputNum; i++) {
            (*pmId)[_AminoAcidAlignoutputId[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 << "AminoAcidAlignFoldedDPTable::getId: WARNING: identifier '" << sId << "' not found." << endl;
        }
        return -1;
    }
    return iter->second;
}


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


bfloat AminoAcidAlignFoldedDPTable::getProb(int iState ,int iPos0,int iPos1) const
{
    const bfloat *CurStateMemoryaaBlock1Secondary;
    const bfloat *CurStateMemoryaaBlock2Secondary;
    const bfloat *CurStateMemoryaaBlock3Secondary;
    static const int blockTable[] = {0, 1, 1, 1, 2};
    static const int stateTable[] = {0, 0, 1, 2, 0};
    switch (blockTable[iState]) {
        default:
        return 0.0;
        break;
        case 0:
        if ((iPos0+0>=0)&&(iPos0+0<=0)&&(iPos1+0>=0)&&(iPos1+0<=0)) {
            CurStateMemoryaaBlock1Secondary = this->StateMemoryaaBlock1.read();
            return CurStateMemoryaaBlock1Secondary[stateTable[iState]];
        } 
        else { 
            return 0.0;
            
        }
        break;
        case 1:
        if ((iPos0+0>=0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=0)&&(iPos1+0<=iLen2+0)) {
            CurStateMemoryaaBlock2Secondary = this->StateMemoryaaBlock2.read((iPos0-(0))-(0), (iPos1-(0))-(0));
            return CurStateMemoryaaBlock2Secondary[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)) {
            CurStateMemoryaaBlock3Secondary = this->StateMemoryaaBlock3.read();
            return CurStateMemoryaaBlock3Secondary[stateTable[iState]];
        } 
        else { 
            return 0.0;
            
        }
    } // switch
} // DPTable...::getProb(int,...)

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


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


void AminoAcidAlignBaumWelch::resetCounts() {
    static bool bInited = false;
    if (!bInited) {
        static const int aTemp[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
        for (int i=0; i<13; i++) {
            transitionIdentifier00[i] = aTemp[i];
            atransitionIdx[aTemp[i]] = i;
            mId[_AminoAcidAligntransitionId[aTemp[i]]] = i;
        }
    }
    for (int i=0; i<13; 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[_AminoAcidAlignemissionId[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[_AminoAcidAlignemissionId[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[_AminoAcidAlignemissionId[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[_AminoAcidAlignemissionId[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 AminoAcidAlignBaumWelch::transitionIdentifier00[];
int AminoAcidAlignBaumWelch::emissionIdentifier00[];
int AminoAcidAlignBaumWelch::emissionIdentifier01[];
int AminoAcidAlignBaumWelch::emissionIdentifier10[];
int AminoAcidAlignBaumWelch::emissionIdentifier11[];

void AminoAcidAlignBaumWelch::scaleCounts(bfloat scale) {
    for (int i=0; i<13; 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> AminoAcidAlignBaumWelch::mId;
int AminoAcidAlignBaumWelch::atransitionIdx[];
int AminoAcidAlignBaumWelch::aemissionIdx[];

const extern string _AminoAcidAlignWithBandingstateId[];
const extern string _AminoAcidAlignWithBandingemissionId[];
const extern string _AminoAcidAlignWithBandingtransitionId[];
const extern string _AminoAcidAlignWithBandingtransF[];
const extern string _AminoAcidAlignWithBandingtransT[];
const extern string _AminoAcidAlignWithBandingtransP[];
const extern string _AminoAcidAlignWithBandingtransE[];
const extern string _AminoAcidAlignWithBandingoutputId[];
const extern string _AminoAcidAlignWithBandingempty;
const extern int _AminoAcidAlignWithBandingstateNum;
const extern int _AminoAcidAlignWithBandingemitNum;
const extern int _AminoAcidAlignWithBandingtransNum;
const extern int _AminoAcidAlignWithBandingoutputNum;

AminoAcidAlignWithBandingDPTable::AminoAcidAlignWithBandingDPTable(int iLen1,int iLen2) : isInCharge(true), stateId(_AminoAcidAlignWithBandingstateId), emissionId(_AminoAcidAlignWithBandingemissionId), transitionId(_AminoAcidAlignWithBandingtransitionId), transitionFrom(_AminoAcidAlignWithBandingtransF), transitionTo(_AminoAcidAlignWithBandingtransT), transitionProb(_AminoAcidAlignWithBandingtransP), transitionEmit(_AminoAcidAlignWithBandingtransE), outputId(_AminoAcidAlignWithBandingoutputId) {
    // init code:
    this->iLen1 = iLen1;
    this->iLen2 = iLen2;
    StateMemoryaaBlock2withbanding.allocate(1+iLen1, 1+iLen2);
    StateMemoryaaBlock1.allocate();
    StateMemoryaaBlock3.allocate();
}


AminoAcidAlignWithBandingDPTable::~AminoAcidAlignWithBandingDPTable() {
    if (!isInCharge) {
        // make sure data does not get deleted:
        StateMemoryaaBlock2withbanding.absolve();
        StateMemoryaaBlock1.absolve();
        StateMemoryaaBlock3.absolve();
    } // if(!isInCharge)
} // destructor

const string& AminoAcidAlignWithBandingDPTable::getTransitionId(int id) { return id>=0 && id<_AminoAcidAlignWithBandingtransNum ? _AminoAcidAlignWithBandingtransitionId[id] : _AminoAcidAlignWithBandingempty; }
const string& AminoAcidAlignWithBandingDPTable::getEmissionId(int id) { return id>=0 && id<_AminoAcidAlignWithBandingemitNum ? _AminoAcidAlignWithBandingemissionId[id] : _AminoAcidAlignWithBandingempty; }
const string& AminoAcidAlignWithBandingDPTable::getStateId(int id) { return id>=0 && id<_AminoAcidAlignWithBandingstateNum ? _AminoAcidAlignWithBandingstateId[id] : _AminoAcidAlignWithBandingempty; }
const string& AminoAcidAlignWithBandingDPTable::getOutputId(int id) { return id>=0 && id<_AminoAcidAlignWithBandingoutputNum ? _AminoAcidAlignWithBandingoutputId[id] : _AminoAcidAlignWithBandingempty; }
int AminoAcidAlignWithBandingDPTable::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<_AminoAcidAlignWithBandingstateNum;i++) {
            (*pmId)[_AminoAcidAlignWithBandingstateId[i]] = i;         // add state identifiers
        }
        for (int i=0; i<_AminoAcidAlignWithBandingemitNum; i++) {
            (*pmId)[_AminoAcidAlignWithBandingemissionId[i]] = i;      // add emission identifiers
        }
        for (int i=0; i<_AminoAcidAlignWithBandingtransNum; i++) {  
            (*pmId)[_AminoAcidAlignWithBandingtransitionId[i]] = i;    // add transition identifiers
        }
        for (int i=0; i<_AminoAcidAlignWithBandingoutputNum; i++) {
            (*pmId)[_AminoAcidAlignWithBandingoutputId[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 << "AminoAcidAlignWithBandingDPTable::getId: WARNING: identifier '" << sId << "' not found." << endl;
        }
        return -1;
    }
    return iter->second;
}


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


bfloat AminoAcidAlignWithBandingDPTable::getProb(int iState ,int iPos0,int iPos1) const
{
    const bfloat *CurStateMemoryaaBlock1Secondary;
    const bfloat *CurStateMemoryaaBlock2withbandingSecondary;
    const bfloat *CurStateMemoryaaBlock3Secondary;
    static const int blockTable[] = {0, 1, 1, 1, 2};
    static const int stateTable[] = {0, 0, 1, 2, 0};
    switch (blockTable[iState]) {
        default:
        return 0.0;
        break;
        case 0:
        if ((iPos0+0>=0)&&(iPos0+0<=0)&&(iPos1+0>=0)&&(iPos1+0<=0)) {
            CurStateMemoryaaBlock1Secondary = this->StateMemoryaaBlock1.read();
            return CurStateMemoryaaBlock1Secondary[stateTable[iState]];
        } 
        else { 
            return 0.0;
            
        }
        break;
        case 1:
        if ((iPos0+0>=0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=0)&&(iPos1+0<=iLen2+0)) {
            CurStateMemoryaaBlock2withbandingSecondary = this->StateMemoryaaBlock2withbanding.read((iPos0-(0))-(0), (iPos1-(0))-(0));
            return CurStateMemoryaaBlock2withbandingSecondary[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)) {
            CurStateMemoryaaBlock3Secondary = this->StateMemoryaaBlock3.read();
            return CurStateMemoryaaBlock3Secondary[stateTable[iState]];
        } 
        else { 
            return 0.0;
            
        }
    } // switch
} // DPTable...::getProb(int,...)

const extern string _AminoAcidAlignWithBandingstateId[];
const extern string _AminoAcidAlignWithBandingemissionId[];
const extern string _AminoAcidAlignWithBandingtransitionId[];
const extern string _AminoAcidAlignWithBandingtransF[];
const extern string _AminoAcidAlignWithBandingtransT[];
const extern string _AminoAcidAlignWithBandingtransP[];
const extern string _AminoAcidAlignWithBandingtransE[];
const extern string _AminoAcidAlignWithBandingoutputId[];
const extern string _AminoAcidAlignWithBandingempty;
const extern int _AminoAcidAlignWithBandingstateNum;
const extern int _AminoAcidAlignWithBandingemitNum;
const extern int _AminoAcidAlignWithBandingtransNum;
const extern int _AminoAcidAlignWithBandingoutputNum;

AminoAcidAlignWithBandingFoldedDPTable::AminoAcidAlignWithBandingFoldedDPTable(int iLen1,int iLen2) : isInCharge(true), stateId(_AminoAcidAlignWithBandingstateId), emissionId(_AminoAcidAlignWithBandingemissionId), transitionId(_AminoAcidAlignWithBandingtransitionId), transitionFrom(_AminoAcidAlignWithBandingtransF), transitionTo(_AminoAcidAlignWithBandingtransT), transitionProb(_AminoAcidAlignWithBandingtransP), transitionEmit(_AminoAcidAlignWithBandingtransE), outputId(_AminoAcidAlignWithBandingoutputId) {
    // init code:
    this->iLen1 = iLen1;
    this->iLen2 = iLen2;
    StateMemoryaaBlock2withbanding.allocate(1+iLen1, 1+iLen2);
    StateMemoryaaBlock3.allocate();
    StateMemoryaaBlock1.allocate();
}


AminoAcidAlignWithBandingFoldedDPTable::~AminoAcidAlignWithBandingFoldedDPTable() {
    if (!isInCharge) {
        // make sure data does not get deleted:
        StateMemoryaaBlock2withbanding.absolve();
        StateMemoryaaBlock3.absolve();
        StateMemoryaaBlock1.absolve();
    } // if(!isInCharge)
} // destructor

const string& AminoAcidAlignWithBandingFoldedDPTable::getTransitionId(int id) { return id>=0 && id<_AminoAcidAlignWithBandingtransNum ? _AminoAcidAlignWithBandingtransitionId[id] : _AminoAcidAlignWithBandingempty; }
const string& AminoAcidAlignWithBandingFoldedDPTable::getEmissionId(int id) { return id>=0 && id<_AminoAcidAlignWithBandingemitNum ? _AminoAcidAlignWithBandingemissionId[id] : _AminoAcidAlignWithBandingempty; }
const string& AminoAcidAlignWithBandingFoldedDPTable::getStateId(int id) { return id>=0 && id<_AminoAcidAlignWithBandingstateNum ? _AminoAcidAlignWithBandingstateId[id] : _AminoAcidAlignWithBandingempty; }
const string& AminoAcidAlignWithBandingFoldedDPTable::getOutputId(int id) { return id>=0 && id<_AminoAcidAlignWithBandingoutputNum ? _AminoAcidAlignWithBandingoutputId[id] : _AminoAcidAlignWithBandingempty; }
int AminoAcidAlignWithBandingFoldedDPTable::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<_AminoAcidAlignWithBandingstateNum;i++) {
            (*pmId)[_AminoAcidAlignWithBandingstateId[i]] = i;         // add state identifiers
        }
        for (int i=0; i<_AminoAcidAlignWithBandingemitNum; i++) {
            (*pmId)[_AminoAcidAlignWithBandingemissionId[i]] = i;      // add emission identifiers
        }
        for (int i=0; i<_AminoAcidAlignWithBandingtransNum; i++) {  
            (*pmId)[_AminoAcidAlignWithBandingtransitionId[i]] = i;    // add transition identifiers
        }
        for (int i=0; i<_AminoAcidAlignWithBandingoutputNum; i++) {
            (*pmId)[_AminoAcidAlignWithBandingoutputId[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 << "AminoAcidAlignWithBandingFoldedDPTable::getId: WARNING: identifier '" << sId << "' not found." << endl;
        }
        return -1;
    }
    return iter->second;
}


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


bfloat AminoAcidAlignWithBandingFoldedDPTable::getProb(int iState ,int iPos0,int iPos1) const
{
    const bfloat *CurStateMemoryaaBlock1Secondary;
    const bfloat *CurStateMemoryaaBlock2withbandingSecondary;
    const bfloat *CurStateMemoryaaBlock3Secondary;
    static const int blockTable[] = {0, 1, 1, 1, 2};
    static const int stateTable[] = {0, 0, 1, 2, 0};
    switch (blockTable[iState]) {
        default:
        return 0.0;
        break;
        case 0:
        if ((iPos0+0>=0)&&(iPos0+0<=0)&&(iPos1+0>=0)&&(iPos1+0<=0)) {
            CurStateMemoryaaBlock1Secondary = this->StateMemoryaaBlock1.read();
            return CurStateMemoryaaBlock1Secondary[stateTable[iState]];
        } 
        else { 
            return 0.0;
            
        }
        break;
        case 1:
        if ((iPos0+0>=0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=0)&&(iPos1+0<=iLen2+0)) {
            CurStateMemoryaaBlock2withbandingSecondary = this->StateMemoryaaBlock2withbanding.read((iPos0-(0))-(0), (iPos1-(0))-(0));
            return CurStateMemoryaaBlock2withbandingSecondary[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)) {
            CurStateMemoryaaBlock3Secondary = this->StateMemoryaaBlock3.read();
            return CurStateMemoryaaBlock3Secondary[stateTable[iState]];
        } 
        else { 
            return 0.0;
            
        }
    } // switch
} // DPTable...::getProb(int,...)

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


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


void AminoAcidAlignWithBandingBaumWelch::resetCounts() {
    static bool bInited = false;
    if (!bInited) {
        static const int aTemp[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
        for (int i=0; i<13; i++) {
            transitionIdentifier00[i] = aTemp[i];
            atransitionIdx[aTemp[i]] = i;
            mId[_AminoAcidAlignWithBandingtransitionId[aTemp[i]]] = i;
        }
    }
    for (int i=0; i<13; 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[_AminoAcidAlignWithBandingemissionId[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[_AminoAcidAlignWithBandingemissionId[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[_AminoAcidAlignWithBandingemissionId[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[_AminoAcidAlignWithBandingemissionId[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 AminoAcidAlignWithBandingBaumWelch::transitionIdentifier00[];
int AminoAcidAlignWithBandingBaumWelch::emissionIdentifier00[];
int AminoAcidAlignWithBandingBaumWelch::emissionIdentifier01[];
int AminoAcidAlignWithBandingBaumWelch::emissionIdentifier10[];
int AminoAcidAlignWithBandingBaumWelch::emissionIdentifier11[];

void AminoAcidAlignWithBandingBaumWelch::scaleCounts(bfloat scale) {
    for (int i=0; i<13; 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> AminoAcidAlignWithBandingBaumWelch::mId;
int AminoAcidAlignWithBandingBaumWelch::atransitionIdx[];
int AminoAcidAlignWithBandingBaumWelch::aemissionIdx[];

const string _AminoAcidAlignstateId[] = {"start","insert1","match","delete1","end"};
const string _AminoAcidAlignemissionId[] = {"emit12","emit2","empty","emit1"};
const string _AminoAcidAligntransitionId[] = {"trSM","trSI1","trSD1","trMM","trMI1","trMD1","trME","trI1M","trI1I1","trI1E","trD1M","trD1D1","trD1E"};
const string _AminoAcidAligntransF[] = {"start","start","start","match","match","match","match","insert1","insert1","insert1","delete1","delete1","delete1"};
const string _AminoAcidAligntransT[] = {"match","insert1","delete1","match","insert1","delete1","end","match","insert1","end","match","delete1","end"};
const string _AminoAcidAligntransP[] = {"probSM","probSI1","probSD1","probMM","probMI1","probMD1","probME","probI1M","probI1I1","probI1E","probD1M","probD1D1","probD1E"};
const string _AminoAcidAligntransE[] = {"emit12","emit1","emit2","emit12","emit1","emit2","empty","emit12","emit1","empty","emit12","emit2","empty"};
const string _AminoAcidAlignoutputId[] = {"sequence1","sequence2"};
const string _AminoAcidAlignempty = "";
const int _AminoAcidAlignstateNum = 5;
const int _AminoAcidAlignemitNum = 4;
const int _AminoAcidAligntransNum = 13;
const int _AminoAcidAlignoutputNum = 2;




bfloat Forward(AminoAcidAlignDPTable** 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[13];
    bfloat *CurStateMemoryaaBlock2To;
    const bfloat *CurStateMemoryaaBlock1From;
    const bfloat *CurStateMemoryaaBlock2From;
    bfloat *CurStateMemoryaaBlock3To;
    const bfloat *CurStateMemoryaaBlock3From;
    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];
    AminoAcidAlignDPTable dp(iLen1,iLen2);
    iTransition[0] = iT[0][1];
    
    iTransition[1] = iT[0][2];
    
    iTransition[2] = iT[0][3];
    
    iTransition[3] = iT[1][1];
    
    iTransition[4] = iT[1][2];
    
    iTransition[5] = iT[1][3];
    
    iTransition[6] = iT[1][6];
    
    iTransition[7] = iT[2][1];
    
    iTransition[8] = iT[2][2];
    
    iTransition[9] = iT[2][6];
    
    iTransition[10] = iT[3][1];
    
    iTransition[11] = iT[3][3];
    
    iTransition[12] = iT[3][6];
    dp.StateMemoryaaBlock1.write()[0] = 1.0;
    dp.StateMemoryaaBlock1.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 */;
                    
                }
                CurStateMemoryaaBlock2To = dp.StateMemoryaaBlock2.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)) {
                    CurStateMemoryaaBlock1From = dp.StateMemoryaaBlock1.read();
                    CurStateMemoryaaBlock2To[2] = ((iTransition[2])*(iEmission[0]))*CurStateMemoryaaBlock1From[0];
                }
                if ((iPos1+-1>=0)) {
                    CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(0))-(0), (iPos1-(1))-(0));
                    CurStateMemoryaaBlock2To[2] += ((iTransition[5])*(iEmission[0]))*CurStateMemoryaaBlock2From[1];
                    CurStateMemoryaaBlock2To[2] += ((iTransition[11])*(iEmission[0]))*CurStateMemoryaaBlock2From[2];
                }
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+-1>=0)&&(iPos0+-1<=0)&&(iPos1+0<=0)) {
                    CurStateMemoryaaBlock1From = dp.StateMemoryaaBlock1.read();
                    CurStateMemoryaaBlock2To[0] = ((iTransition[1])*(iEmission[0]))*CurStateMemoryaaBlock1From[0];
                }
                if ((iPos0+-1>=0)) {
                    CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(1))-(0), (iPos1-(0))-(0));
                    CurStateMemoryaaBlock2To[0] += ((iTransition[4])*(iEmission[0]))*CurStateMemoryaaBlock2From[1];
                    CurStateMemoryaaBlock2To[0] += ((iTransition[8])*(iEmission[0]))*CurStateMemoryaaBlock2From[0];
                }
                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)) {
                    CurStateMemoryaaBlock1From = dp.StateMemoryaaBlock1.read();
                    CurStateMemoryaaBlock2To[1] = ((iTransition[0])*(iEmission[0]))*CurStateMemoryaaBlock1From[0];
                }
                if ((iPos0+-1>=0)&&(iPos1+-1>=0)) {
                    CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(1))-(0), (iPos1-(1))-(0));
                    CurStateMemoryaaBlock2To[1] += ((iTransition[3])*(iEmission[0]))*CurStateMemoryaaBlock2From[1];
                    CurStateMemoryaaBlock2To[1] += ((iTransition[7])*(iEmission[0]))*CurStateMemoryaaBlock2From[0];
                    CurStateMemoryaaBlock2To[1] += ((iTransition[10])*(iEmission[0]))*CurStateMemoryaaBlock2From[2];
                }
                dp.StateMemoryaaBlock2.written();
            }
            if ((iPos0+0>=iLen1+0)&&(iPos1+0>=iLen2+0)) {
                CurStateMemoryaaBlock3To = dp.StateMemoryaaBlock3.write();
                iEmission[0] = 1.0;
                if (1) {
                    CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(0))-(0), (iPos1-(0))-(0));
                    CurStateMemoryaaBlock3To[0] = ((iTransition[6])*(iEmission[0]))*CurStateMemoryaaBlock2From[1];
                    CurStateMemoryaaBlock3To[0] += ((iTransition[9])*(iEmission[0]))*CurStateMemoryaaBlock2From[0];
                    CurStateMemoryaaBlock3To[0] += ((iTransition[12])*(iEmission[0]))*CurStateMemoryaaBlock2From[2];
                }
                dp.StateMemoryaaBlock3.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
            CurStateMemoryaaBlock3From = dp.StateMemoryaaBlock3.read();
            iTempProb[0] = CurStateMemoryaaBlock3From[0];
        }
    }
    *ppOutTable = new AminoAcidAlignDPTable(dp);
    // make sure tables don't get deleted
    dp.isInCharge = false;
    return iTempProb[0];
};





bfloat BackwardBaumWelch(AminoAcidAlignBaumWelch& bw,AminoAcidAlignDPTable* 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 *CurStateMemoryaaBlock3Secondary;
    bfloat iTransition[13];
    bfloat *CurStateMemoryaaBlock2To;
    const bfloat *CurStateMemoryaaBlock2Secondary;
    const bfloat *CurStateMemoryaaBlock2From;
    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 *CurStateMemoryaaBlock3From;
    bfloat *CurStateMemoryaaBlock1To;
    const bfloat *CurStateMemoryaaBlock1Secondary;
    const bfloat *CurStateMemoryaaBlock1From;
    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];
    AminoAcidAlignFoldedDPTable dp(iLen1,2);
    AminoAcidAlignDPTable 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[1][1];
    
    iTransition[4] = iT[1][2];
    
    iTransition[5] = iT[1][3];
    
    iTransition[6] = iT[1][6];
    
    iTransition[7] = iT[2][1];
    
    iTransition[8] = iT[2][2];
    
    iTransition[9] = iT[2][6];
    
    iTransition[10] = iT[3][1];
    
    iTransition[11] = iT[3][3];
    
    iTransition[12] = iT[3][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.StateMemoryaaBlock3.write()[0] = 1.0;
    dp.StateMemoryaaBlock3.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
            CurStateMemoryaaBlock3Secondary = dp2.StateMemoryaaBlock3.read();
            iTempProb[2] = CurStateMemoryaaBlock3Secondary[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.StateMemoryaaBlock2.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 */;
                    
                }
                CurStateMemoryaaBlock2To = dp.StateMemoryaaBlock2.write((iPos0-(0))-(0), (iPos1-(0))-(0));
                CurStateMemoryaaBlock2Secondary = dp2.StateMemoryaaBlock2.read((iPos0-(0))-(0), (iPos1-(0))-(0));
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos1+1<=iLen2+0)) {
                    CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
                    CurStateMemoryaaBlock2To[2] = iTempProb[1] = ((iTransition[11])*(iEmission[0]))*CurStateMemoryaaBlock2From[2];
                    iTempProb[1] *= CurStateMemoryaaBlock2Secondary[2];
                    bw.transitionBaumWelchCount00[11] += iTempProb[1];
                    bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                    CurStateMemoryaaBlock2To[1] = iTempProb[1] = ((iTransition[5])*(iEmission[0]))*CurStateMemoryaaBlock2From[2];
                    iTempProb[1] *= CurStateMemoryaaBlock2Secondary[1];
                    bw.transitionBaumWelchCount00[5] += 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)) {
                    CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
                    CurStateMemoryaaBlock2To[0] = iTempProb[1] = ((iTransition[8])*(iEmission[0]))*CurStateMemoryaaBlock2From[0];
                    iTempProb[1] *= CurStateMemoryaaBlock2Secondary[0];
                    bw.transitionBaumWelchCount00[8] += iTempProb[1];
                    bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
                    CurStateMemoryaaBlock2To[1] += iTempProb[1] = ((iTransition[4])*(iEmission[0]))*CurStateMemoryaaBlock2From[0];
                    iTempProb[1] *= CurStateMemoryaaBlock2Secondary[1];
                    bw.transitionBaumWelchCount00[4] += 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)) {
                    CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
                    CurStateMemoryaaBlock2To[2] += iTempProb[1] = ((iTransition[10])*(iEmission[0]))*CurStateMemoryaaBlock2From[1];
                    iTempProb[1] *= CurStateMemoryaaBlock2Secondary[2];
                    bw.transitionBaumWelchCount00[10] += iTempProb[1];
                    bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                    CurStateMemoryaaBlock2To[0] += iTempProb[1] = ((iTransition[7])*(iEmission[0]))*CurStateMemoryaaBlock2From[1];
                    iTempProb[1] *= CurStateMemoryaaBlock2Secondary[0];
                    bw.transitionBaumWelchCount00[7] += iTempProb[1];
                    bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                    CurStateMemoryaaBlock2To[1] += iTempProb[1] = ((iTransition[3])*(iEmission[0]))*CurStateMemoryaaBlock2From[1];
                    iTempProb[1] *= CurStateMemoryaaBlock2Secondary[1];
                    bw.transitionBaumWelchCount00[3] += 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)) {
                    CurStateMemoryaaBlock3From = dp.StateMemoryaaBlock3.read();
                    CurStateMemoryaaBlock2To[2] += iTempProb[1] = ((iTransition[12])*(iEmission[0]))*CurStateMemoryaaBlock3From[0];
                    iTempProb[1] *= CurStateMemoryaaBlock2Secondary[2];
                    bw.transitionBaumWelchCount00[12] += iTempProb[1];
                    bw.emissionBaumWelchCount00[0] += iTempProb[1];
                    CurStateMemoryaaBlock2To[0] += iTempProb[1] = ((iTransition[9])*(iEmission[0]))*CurStateMemoryaaBlock3From[0];
                    iTempProb[1] *= CurStateMemoryaaBlock2Secondary[0];
                    bw.transitionBaumWelchCount00[9] += iTempProb[1];
                    bw.emissionBaumWelchCount00[0] += iTempProb[1];
                    CurStateMemoryaaBlock2To[1] += iTempProb[1] = ((iTransition[6])*(iEmission[0]))*CurStateMemoryaaBlock3From[0];
                    iTempProb[1] *= CurStateMemoryaaBlock2Secondary[1];
                    bw.transitionBaumWelchCount00[6] += iTempProb[1];
                    bw.emissionBaumWelchCount00[0] += iTempProb[1];
                }
                dp.StateMemoryaaBlock2.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 */;
                    
                }
                CurStateMemoryaaBlock1To = dp.StateMemoryaaBlock1.write();
                CurStateMemoryaaBlock1Secondary = dp2.StateMemoryaaBlock1.read();
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos1+1<=iLen2+0)) {
                    CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
                    CurStateMemoryaaBlock1To[0] = iTempProb[1] = ((iTransition[2])*(iEmission[0]))*CurStateMemoryaaBlock2From[2];
                    iTempProb[1] *= CurStateMemoryaaBlock1Secondary[0];
                    bw.transitionBaumWelchCount00[2] += 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)) {
                    CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
                    CurStateMemoryaaBlock1To[0] += iTempProb[1] = ((iTransition[1])*(iEmission[0]))*CurStateMemoryaaBlock2From[0];
                    iTempProb[1] *= CurStateMemoryaaBlock1Secondary[0];
                    bw.transitionBaumWelchCount00[1] += 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)) {
                    CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
                    CurStateMemoryaaBlock1To[0] += iTempProb[1] = ((iTransition[0])*(iEmission[0]))*CurStateMemoryaaBlock2From[1];
                    iTempProb[1] *= CurStateMemoryaaBlock1Secondary[0];
                    bw.transitionBaumWelchCount00[0] += iTempProb[1];
                    bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                }
                dp.StateMemoryaaBlock1.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
            CurStateMemoryaaBlock1From = dp.StateMemoryaaBlock1.read();
            iTempProb[0] = CurStateMemoryaaBlock1From[0];
        }
    }
    return iTempProb[0];
};





bfloat Backward(AminoAcidAlignDPTable** 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[13];
    bfloat *CurStateMemoryaaBlock2To;
    const bfloat *CurStateMemoryaaBlock2From;
    const bfloat *CurStateMemoryaaBlock3From;
    bfloat *CurStateMemoryaaBlock1To;
    const bfloat *CurStateMemoryaaBlock1From;
    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];
    AminoAcidAlignDPTable dp(iLen1,iLen2);
    iTransition[0] = iT[0][1];
    
    iTransition[1] = iT[0][2];
    
    iTransition[2] = iT[0][3];
    
    iTransition[3] = iT[1][1];
    
    iTransition[4] = iT[1][2];
    
    iTransition[5] = iT[1][3];
    
    iTransition[6] = iT[1][6];
    
    iTransition[7] = iT[2][1];
    
    iTransition[8] = iT[2][2];
    
    iTransition[9] = iT[2][6];
    
    iTransition[10] = iT[3][1];
    
    iTransition[11] = iT[3][3];
    
    iTransition[12] = iT[3][6];
    dp.StateMemoryaaBlock3.write()[0] = 1.0;
    dp.StateMemoryaaBlock3.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 */;
                    
                }
                CurStateMemoryaaBlock2To = dp.StateMemoryaaBlock2.write((iPos0-(0))-(0), (iPos1-(0))-(0));
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos1+1<=iLen2+0)) {
                    CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
                    CurStateMemoryaaBlock2To[2] = ((iTransition[11])*(iEmission[0]))*CurStateMemoryaaBlock2From[2];
                    CurStateMemoryaaBlock2To[1] = ((iTransition[5])*(iEmission[0]))*CurStateMemoryaaBlock2From[2];
                }
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+1<=iLen1+0)) {
                    CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
                    CurStateMemoryaaBlock2To[0] = ((iTransition[8])*(iEmission[0]))*CurStateMemoryaaBlock2From[0];
                    CurStateMemoryaaBlock2To[1] += ((iTransition[4])*(iEmission[0]))*CurStateMemoryaaBlock2From[0];
                }
                iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
                    CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
                    CurStateMemoryaaBlock2To[2] += ((iTransition[10])*(iEmission[0]))*CurStateMemoryaaBlock2From[1];
                    CurStateMemoryaaBlock2To[0] += ((iTransition[7])*(iEmission[0]))*CurStateMemoryaaBlock2From[1];
                    CurStateMemoryaaBlock2To[1] += ((iTransition[3])*(iEmission[0]))*CurStateMemoryaaBlock2From[1];
                }
                iEmission[0] = 1.0;
                if ((iPos0+0>=iLen1+0)&&(iPos1+0>=iLen2+0)) {
                    CurStateMemoryaaBlock3From = dp.StateMemoryaaBlock3.read();
                    CurStateMemoryaaBlock2To[2] += ((iTransition[12])*(iEmission[0]))*CurStateMemoryaaBlock3From[0];
                    CurStateMemoryaaBlock2To[0] += ((iTransition[9])*(iEmission[0]))*CurStateMemoryaaBlock3From[0];
                    CurStateMemoryaaBlock2To[1] += ((iTransition[6])*(iEmission[0]))*CurStateMemoryaaBlock3From[0];
                }
                dp.StateMemoryaaBlock2.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 */;
                    
                }
                CurStateMemoryaaBlock1To = dp.StateMemoryaaBlock1.write();
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos1+1<=iLen2+0)) {
                    CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
                    CurStateMemoryaaBlock1To[0] = ((iTransition[2])*(iEmission[0]))*CurStateMemoryaaBlock2From[2];
                }
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+1<=iLen1+0)) {
                    CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
                    CurStateMemoryaaBlock1To[0] += ((iTransition[1])*(iEmission[0]))*CurStateMemoryaaBlock2From[0];
                }
                iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
                    CurStateMemoryaaBlock2From = dp.StateMemoryaaBlock2.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
                    CurStateMemoryaaBlock1To[0] += ((iTransition[0])*(iEmission[0]))*CurStateMemoryaaBlock2From[1];
                }
                dp.StateMemoryaaBlock1.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
            CurStateMemoryaaBlock1From = dp.StateMemoryaaBlock1.read();
            iTempProb[0] = CurStateMemoryaaBlock1From[0];
        }
    }
    *ppOutTable = new AminoAcidAlignDPTable(dp);
    // make sure tables don't get deleted
    dp.isInCharge = false;
    return iTempProb[0];
};



const string _AminoAcidAlignWithBandingstateId[] = {"start","insert1","match","delete1","end"};
const string _AminoAcidAlignWithBandingemissionId[] = {"emit12","emit2","empty","emit1"};
const string _AminoAcidAlignWithBandingtransitionId[] = {"trSM","trSI1","trSD1","trMM","trMI1","trMD1","trME","trI1M","trI1I1","trI1E","trD1M","trD1D1","trD1E"};
const string _AminoAcidAlignWithBandingtransF[] = {"start","start","start","match","match","match","match","insert1","insert1","insert1","delete1","delete1","delete1"};
const string _AminoAcidAlignWithBandingtransT[] = {"match","insert1","delete1","match","insert1","delete1","end","match","insert1","end","match","delete1","end"};
const string _AminoAcidAlignWithBandingtransP[] = {"probSM","probSI1","probSD1","probMM","probMI1","probMD1","probME","probI1M","probI1I1","probI1E","probD1M","probD1D1","probD1E"};
const string _AminoAcidAlignWithBandingtransE[] = {"emit12","emit1","emit2","emit12","emit1","emit2","empty","emit12","emit1","empty","emit12","emit2","empty"};
const string _AminoAcidAlignWithBandingoutputId[] = {"sequence1","sequence2"};
const string _AminoAcidAlignWithBandingempty = "";
const int _AminoAcidAlignWithBandingstateNum = 5;
const int _AminoAcidAlignWithBandingemitNum = 4;
const int _AminoAcidAlignWithBandingtransNum = 13;
const int _AminoAcidAlignWithBandingoutputNum = 2;




bfloat ForwardBanding(AminoAcidAlignWithBandingDPTable** 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[13];
    bfloat *CurStateMemoryaaBlock2withbandingTo;
    const bfloat *CurStateMemoryaaBlock1From;
    const bfloat *CurStateMemoryaaBlock2withbandingFrom;
    bfloat *CurStateMemoryaaBlock3To;
    const bfloat *CurStateMemoryaaBlock3From;
    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];
    AminoAcidAlignWithBandingDPTable dp(iLen1,iLen2);
    iTransition[0] = iT[0][1];
    
    iTransition[1] = iT[0][2];
    
    iTransition[2] = iT[0][3];
    
    iTransition[3] = iT[1][1];
    
    iTransition[4] = iT[1][2];
    
    iTransition[5] = iT[1][3];
    
    iTransition[6] = iT[1][6];
    
    iTransition[7] = iT[2][1];
    
    iTransition[8] = iT[2][2];
    
    iTransition[9] = iT[2][6];
    
    iTransition[10] = iT[3][1];
    
    iTransition[11] = iT[3][3];
    
    iTransition[12] = iT[3][6];
    dp.StateMemoryaaBlock1.write()[0] = 1.0;
    dp.StateMemoryaaBlock1.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 */;
                        
                    }
                    CurStateMemoryaaBlock2withbandingTo = dp.StateMemoryaaBlock2withbanding.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)) {
                        CurStateMemoryaaBlock1From = dp.StateMemoryaaBlock1.read();
                        CurStateMemoryaaBlock2withbandingTo[2] = ((iTransition[2])*(iEmission[0]))*CurStateMemoryaaBlock1From[0];
                    }
                    if ((position[1]+-1>=0)) {
                        CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((position[0]-(0))-(0), (position[1]-(1))-(0));
                        CurStateMemoryaaBlock2withbandingTo[2] += ((iTransition[11])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[2];
                        CurStateMemoryaaBlock2withbandingTo[2] += ((iTransition[5])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[1];
                    }
                    iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
                    iEmission[0] = iTempResult[0];
                    if ((position[0]+-1>=0)&&(position[0]+-1<=0)&&(position[1]+0<=0)) {
                        CurStateMemoryaaBlock1From = dp.StateMemoryaaBlock1.read();
                        CurStateMemoryaaBlock2withbandingTo[0] = ((iTransition[1])*(iEmission[0]))*CurStateMemoryaaBlock1From[0];
                    }
                    if ((position[0]+-1>=0)) {
                        CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((position[0]-(1))-(0), (position[1]-(0))-(0));
                        CurStateMemoryaaBlock2withbandingTo[0] += ((iTransition[4])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[1];
                        CurStateMemoryaaBlock2withbandingTo[0] += ((iTransition[8])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[0];
                    }
                    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)) {
                        CurStateMemoryaaBlock1From = dp.StateMemoryaaBlock1.read();
                        CurStateMemoryaaBlock2withbandingTo[1] = ((iTransition[0])*(iEmission[0]))*CurStateMemoryaaBlock1From[0];
                    }
                    if ((position[0]+-1>=0)&&(position[1]+-1>=0)) {
                        CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((position[0]-(1))-(0), (position[1]-(1))-(0));
                        CurStateMemoryaaBlock2withbandingTo[1] += ((iTransition[10])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[2];
                        CurStateMemoryaaBlock2withbandingTo[1] += ((iTransition[3])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[1];
                        CurStateMemoryaaBlock2withbandingTo[1] += ((iTransition[7])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[0];
                    }
                    dp.StateMemoryaaBlock2withbanding.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) {
                CurStateMemoryaaBlock3To = dp.StateMemoryaaBlock3.write();
                iEmission[0] = 1.0;
                if (1) {
                    CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((iPos0-(0))-(0), (iPos1-(0))-(0));
                    CurStateMemoryaaBlock3To[0] = ((iTransition[12])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[2];
                    CurStateMemoryaaBlock3To[0] += ((iTransition[6])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[1];
                    CurStateMemoryaaBlock3To[0] += ((iTransition[9])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[0];
                }
                dp.StateMemoryaaBlock3.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
            CurStateMemoryaaBlock3From = dp.StateMemoryaaBlock3.read();
            iTempProb[0] = CurStateMemoryaaBlock3From[0];
        }
    }
    *ppOutTable = new AminoAcidAlignWithBandingDPTable(dp);
    // make sure tables don't get deleted
    dp.isInCharge = false;
    return iTempProb[0];
};





bfloat BackwardBaumWelchBanding(AminoAcidAlignWithBandingBaumWelch& bw,AminoAcidAlignWithBandingDPTable* 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 *CurStateMemoryaaBlock3Secondary;
    bfloat iTransition[13];
    bfloat *CurStateMemoryaaBlock2withbandingTo;
    const bfloat *CurStateMemoryaaBlock2withbandingSecondary;
    const bfloat *CurStateMemoryaaBlock2withbandingFrom;
    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 *CurStateMemoryaaBlock3From;
    bfloat *CurStateMemoryaaBlock1To;
    const bfloat *CurStateMemoryaaBlock1Secondary;
    const bfloat *CurStateMemoryaaBlock1From;
    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];
    AminoAcidAlignWithBandingFoldedDPTable dp(iLen1,2);
    AminoAcidAlignWithBandingDPTable 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[1][1];
    
    iTransition[4] = iT[1][2];
    
    iTransition[5] = iT[1][3];
    
    iTransition[6] = iT[1][6];
    
    iTransition[7] = iT[2][1];
    
    iTransition[8] = iT[2][2];
    
    iTransition[9] = iT[2][6];
    
    iTransition[10] = iT[3][1];
    
    iTransition[11] = iT[3][3];
    
    iTransition[12] = iT[3][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.StateMemoryaaBlock3.write()[0] = 1.0;
    dp.StateMemoryaaBlock3.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
            CurStateMemoryaaBlock3Secondary = dp2.StateMemoryaaBlock3.read();
            iTempProb[2] = CurStateMemoryaaBlock3Secondary[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.StateMemoryaaBlock2withbanding.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 */;
                        
                    }
                    CurStateMemoryaaBlock2withbandingTo = dp.StateMemoryaaBlock2withbanding.write((position[0]-(0))-(0), (position[1]-(0))-(0));
                    CurStateMemoryaaBlock2withbandingSecondary = dp2.StateMemoryaaBlock2withbanding.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)) {
                        CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((position[0]-(0))-(0), (position[1]-(-1))-(0));
                        CurStateMemoryaaBlock2withbandingTo[2] = iTempProb[1] = ((iTransition[11])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[2];
                        iTempProb[1] *= CurStateMemoryaaBlock2withbandingSecondary[2];
                        bw.transitionBaumWelchCount00[11] += iTempProb[1];
                        bw.emissionBaumWelchCount01[alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                        CurStateMemoryaaBlock2withbandingTo[1] = iTempProb[1] = ((iTransition[5])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[2];
                        iTempProb[1] *= CurStateMemoryaaBlock2withbandingSecondary[1];
                        bw.transitionBaumWelchCount00[5] += 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)) {
                        CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((position[0]-(-1))-(0), (position[1]-(0))-(0));
                        CurStateMemoryaaBlock2withbandingTo[1] += iTempProb[1] = ((iTransition[4])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[0];
                        iTempProb[1] *= CurStateMemoryaaBlock2withbandingSecondary[1];
                        bw.transitionBaumWelchCount00[4] += iTempProb[1];
                        bw.emissionBaumWelchCount10[alphaIndexaminoacid[iSymbol[1]]][0] += iTempProb[1];
                        CurStateMemoryaaBlock2withbandingTo[0] = iTempProb[1] = ((iTransition[8])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[0];
                        iTempProb[1] *= CurStateMemoryaaBlock2withbandingSecondary[0];
                        bw.transitionBaumWelchCount00[8] += 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)) {
                        CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((position[0]-(-1))-(0), (position[1]-(-1))-(0));
                        CurStateMemoryaaBlock2withbandingTo[2] += iTempProb[1] = ((iTransition[10])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[1];
                        iTempProb[1] *= CurStateMemoryaaBlock2withbandingSecondary[2];
                        bw.transitionBaumWelchCount00[10] += iTempProb[1];
                        bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                        CurStateMemoryaaBlock2withbandingTo[1] += iTempProb[1] = ((iTransition[3])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[1];
                        iTempProb[1] *= CurStateMemoryaaBlock2withbandingSecondary[1];
                        bw.transitionBaumWelchCount00[3] += iTempProb[1];
                        bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                        CurStateMemoryaaBlock2withbandingTo[0] += iTempProb[1] = ((iTransition[7])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[1];
                        iTempProb[1] *= CurStateMemoryaaBlock2withbandingSecondary[0];
                        bw.transitionBaumWelchCount00[7] += 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)) {
                        CurStateMemoryaaBlock3From = dp.StateMemoryaaBlock3.read();
                        CurStateMemoryaaBlock2withbandingTo[2] += iTempProb[1] = ((iTransition[12])*(iEmission[0]))*CurStateMemoryaaBlock3From[0];
                        iTempProb[1] *= CurStateMemoryaaBlock2withbandingSecondary[2];
                        bw.transitionBaumWelchCount00[12] += iTempProb[1];
                        bw.emissionBaumWelchCount00[0] += iTempProb[1];
                        CurStateMemoryaaBlock2withbandingTo[1] += iTempProb[1] = ((iTransition[6])*(iEmission[0]))*CurStateMemoryaaBlock3From[0];
                        iTempProb[1] *= CurStateMemoryaaBlock2withbandingSecondary[1];
                        bw.transitionBaumWelchCount00[6] += iTempProb[1];
                        bw.emissionBaumWelchCount00[0] += iTempProb[1];
                        CurStateMemoryaaBlock2withbandingTo[0] += iTempProb[1] = ((iTransition[9])*(iEmission[0]))*CurStateMemoryaaBlock3From[0];
                        iTempProb[1] *= CurStateMemoryaaBlock2withbandingSecondary[0];
                        bw.transitionBaumWelchCount00[9] += iTempProb[1];
                        bw.emissionBaumWelchCount00[0] += iTempProb[1];
                    }
                    dp.StateMemoryaaBlock2withbanding.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 */;
                    
                }
                CurStateMemoryaaBlock1To = dp.StateMemoryaaBlock1.write();
                CurStateMemoryaaBlock1Secondary = dp2.StateMemoryaaBlock1.read();
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos1+1<=iLen2+0)) {
                    CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
                    CurStateMemoryaaBlock1To[0] = iTempProb[1] = ((iTransition[2])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[2];
                    iTempProb[1] *= CurStateMemoryaaBlock1Secondary[0];
                    bw.transitionBaumWelchCount00[2] += 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)) {
                    CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
                    CurStateMemoryaaBlock1To[0] += iTempProb[1] = ((iTransition[1])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[0];
                    iTempProb[1] *= CurStateMemoryaaBlock1Secondary[0];
                    bw.transitionBaumWelchCount00[1] += 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)) {
                    CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
                    CurStateMemoryaaBlock1To[0] += iTempProb[1] = ((iTransition[0])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[1];
                    iTempProb[1] *= CurStateMemoryaaBlock1Secondary[0];
                    bw.transitionBaumWelchCount00[0] += iTempProb[1];
                    bw.emissionBaumWelchCount11[alphaIndexaminoacid[iSymbol[1]]][alphaIndexaminoacid[iSymbol[0]]][0] += iTempProb[1];
                }
                dp.StateMemoryaaBlock1.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
            CurStateMemoryaaBlock1From = dp.StateMemoryaaBlock1.read();
            iTempProb[0] = CurStateMemoryaaBlock1From[0];
        }
    }
    return iTempProb[0];
};





bfloat BackwardBanding(AminoAcidAlignWithBandingDPTable** 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[13];
    bfloat *CurStateMemoryaaBlock2withbandingTo;
    const bfloat *CurStateMemoryaaBlock2withbandingFrom;
    const bfloat *CurStateMemoryaaBlock3From;
    bfloat *CurStateMemoryaaBlock1To;
    const bfloat *CurStateMemoryaaBlock1From;
    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];
    AminoAcidAlignWithBandingDPTable dp(iLen1,iLen2);
    iTransition[0] = iT[0][1];
    
    iTransition[1] = iT[0][2];
    
    iTransition[2] = iT[0][3];
    
    iTransition[3] = iT[1][1];
    
    iTransition[4] = iT[1][2];
    
    iTransition[5] = iT[1][3];
    
    iTransition[6] = iT[1][6];
    
    iTransition[7] = iT[2][1];
    
    iTransition[8] = iT[2][2];
    
    iTransition[9] = iT[2][6];
    
    iTransition[10] = iT[3][1];
    
    iTransition[11] = iT[3][3];
    
    iTransition[12] = iT[3][6];
    dp.StateMemoryaaBlock3.write()[0] = 1.0;
    dp.StateMemoryaaBlock3.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 */;
                        
                    }
                    CurStateMemoryaaBlock2withbandingTo = dp.StateMemoryaaBlock2withbanding.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)) {
                        CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((position[0]-(0))-(0), (position[1]-(-1))-(0));
                        CurStateMemoryaaBlock2withbandingTo[1] = ((iTransition[5])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[2];
                        CurStateMemoryaaBlock2withbandingTo[2] = ((iTransition[11])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[2];
                    }
                    iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
                    iEmission[0] = iTempResult[0];
                    if ((position[0]+1<=iLen1+0)) {
                        CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((position[0]-(-1))-(0), (position[1]-(0))-(0));
                        CurStateMemoryaaBlock2withbandingTo[1] += ((iTransition[4])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[0];
                        CurStateMemoryaaBlock2withbandingTo[0] = ((iTransition[8])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[0];
                    }
                    iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
                    iEmission[0] = iTempResult[0];
                    if ((position[0]+1<=iLen1+0)&&(position[1]+1<=iLen2+0)) {
                        CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((position[0]-(-1))-(0), (position[1]-(-1))-(0));
                        CurStateMemoryaaBlock2withbandingTo[2] += ((iTransition[10])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[1];
                        CurStateMemoryaaBlock2withbandingTo[1] += ((iTransition[3])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[1];
                        CurStateMemoryaaBlock2withbandingTo[0] += ((iTransition[7])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[1];
                    }
                    iEmission[0] = 1.0;
                    if ((position[0]+0>=iLen1+0)&&(position[1]+0>=iLen2+0)) {
                        CurStateMemoryaaBlock3From = dp.StateMemoryaaBlock3.read();
                        CurStateMemoryaaBlock2withbandingTo[2] += ((iTransition[12])*(iEmission[0]))*CurStateMemoryaaBlock3From[0];
                        CurStateMemoryaaBlock2withbandingTo[1] += ((iTransition[6])*(iEmission[0]))*CurStateMemoryaaBlock3From[0];
                        CurStateMemoryaaBlock2withbandingTo[0] += ((iTransition[9])*(iEmission[0]))*CurStateMemoryaaBlock3From[0];
                    }
                    dp.StateMemoryaaBlock2withbanding.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 */;
                    
                }
                CurStateMemoryaaBlock1To = dp.StateMemoryaaBlock1.write();
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos1+1<=iLen2+0)) {
                    CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
                    CurStateMemoryaaBlock1To[0] = ((iTransition[2])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[2];
                }
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+1<=iLen1+0)) {
                    CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
                    CurStateMemoryaaBlock1To[0] += ((iTransition[1])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[0];
                }
                iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
                    CurStateMemoryaaBlock2withbandingFrom = dp.StateMemoryaaBlock2withbanding.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
                    CurStateMemoryaaBlock1To[0] += ((iTransition[0])*(iEmission[0]))*CurStateMemoryaaBlock2withbandingFrom[1];
                }
                dp.StateMemoryaaBlock1.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
            CurStateMemoryaaBlock1From = dp.StateMemoryaaBlock1.read();
            iTempProb[0] = CurStateMemoryaaBlock1From[0];
        }
    }
    *ppOutTable = new AminoAcidAlignWithBandingDPTable(dp);
    // make sure tables don't get deleted
    dp.isInCharge = false;
    return iTempProb[0];
};



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