/* Code generated by HMMoC version 1.3, Copyright (C) 2006 Gerton Lunter */
/* Generated from file nucleotide.xml (author:  Robert K. Bradley ) on Tue Dec 23 01:04:16 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 "nucleotidedp.h"

#include "mybanding.h"

const extern string _NucleotideAlignstateId[];
const extern string _NucleotideAlignemissionId[];
const extern string _NucleotideAligntransitionId[];
const extern string _NucleotideAligntransF[];
const extern string _NucleotideAligntransT[];
const extern string _NucleotideAligntransP[];
const extern string _NucleotideAligntransE[];
const extern string _NucleotideAlignoutputId[];
const extern string _NucleotideAlignempty;
const extern int _NucleotideAlignstateNum;
const extern int _NucleotideAlignemitNum;
const extern int _NucleotideAligntransNum;
const extern int _NucleotideAlignoutputNum;

NucleotideAlignDPTable::NucleotideAlignDPTable(int iLen1,int iLen2) : isInCharge(true), stateId(_NucleotideAlignstateId), emissionId(_NucleotideAlignemissionId), transitionId(_NucleotideAligntransitionId), transitionFrom(_NucleotideAligntransF), transitionTo(_NucleotideAligntransT), transitionProb(_NucleotideAligntransP), transitionEmit(_NucleotideAligntransE), outputId(_NucleotideAlignoutputId) {
    // init code:
    this->iLen1 = iLen1;
    this->iLen2 = iLen2;
    StateMemorynucBlock2.allocate(1+iLen1, 1+iLen2);
    StateMemorynucBlock1.allocate();
    StateMemorynucBlock3.allocate();
}


NucleotideAlignDPTable::~NucleotideAlignDPTable() {
    if (!isInCharge) {
        // make sure data does not get deleted:
        StateMemorynucBlock2.absolve();
        StateMemorynucBlock1.absolve();
        StateMemorynucBlock3.absolve();
    } // if(!isInCharge)
} // destructor

const string& NucleotideAlignDPTable::getTransitionId(int id) { return id>=0 && id<_NucleotideAligntransNum ? _NucleotideAligntransitionId[id] : _NucleotideAlignempty; }
const string& NucleotideAlignDPTable::getEmissionId(int id) { return id>=0 && id<_NucleotideAlignemitNum ? _NucleotideAlignemissionId[id] : _NucleotideAlignempty; }
const string& NucleotideAlignDPTable::getStateId(int id) { return id>=0 && id<_NucleotideAlignstateNum ? _NucleotideAlignstateId[id] : _NucleotideAlignempty; }
const string& NucleotideAlignDPTable::getOutputId(int id) { return id>=0 && id<_NucleotideAlignoutputNum ? _NucleotideAlignoutputId[id] : _NucleotideAlignempty; }
int NucleotideAlignDPTable::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<_NucleotideAlignstateNum;i++) {
            (*pmId)[_NucleotideAlignstateId[i]] = i;         // add state identifiers
        }
        for (int i=0; i<_NucleotideAlignemitNum; i++) {
            (*pmId)[_NucleotideAlignemissionId[i]] = i;      // add emission identifiers
        }
        for (int i=0; i<_NucleotideAligntransNum; i++) {  
            (*pmId)[_NucleotideAligntransitionId[i]] = i;    // add transition identifiers
        }
        for (int i=0; i<_NucleotideAlignoutputNum; i++) {
            (*pmId)[_NucleotideAlignoutputId[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 << "NucleotideAlignDPTable::getId: WARNING: identifier '" << sId << "' not found." << endl;
        }
        return -1;
    }
    return iter->second;
}


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


bfloat NucleotideAlignDPTable::getProb(int iState ,int iPos0,int iPos1) const
{
    const bfloat *CurStateMemorynucBlock1Secondary;
    const bfloat *CurStateMemorynucBlock2Secondary;
    const bfloat *CurStateMemorynucBlock3Secondary;
    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)) {
            CurStateMemorynucBlock1Secondary = this->StateMemorynucBlock1.read();
            return CurStateMemorynucBlock1Secondary[stateTable[iState]];
        } 
        else { 
            return 0.0;
            
        }
        break;
        case 1:
        if ((iPos0+0>=0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=0)&&(iPos1+0<=iLen2+0)) {
            CurStateMemorynucBlock2Secondary = this->StateMemorynucBlock2.read((iPos0-(0))-(0), (iPos1-(0))-(0));
            return CurStateMemorynucBlock2Secondary[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)) {
            CurStateMemorynucBlock3Secondary = this->StateMemorynucBlock3.read();
            return CurStateMemorynucBlock3Secondary[stateTable[iState]];
        } 
        else { 
            return 0.0;
            
        }
    } // switch
} // DPTable...::getProb(int,...)

const extern string _NucleotideAlignstateId[];
const extern string _NucleotideAlignemissionId[];
const extern string _NucleotideAligntransitionId[];
const extern string _NucleotideAligntransF[];
const extern string _NucleotideAligntransT[];
const extern string _NucleotideAligntransP[];
const extern string _NucleotideAligntransE[];
const extern string _NucleotideAlignoutputId[];
const extern string _NucleotideAlignempty;
const extern int _NucleotideAlignstateNum;
const extern int _NucleotideAlignemitNum;
const extern int _NucleotideAligntransNum;
const extern int _NucleotideAlignoutputNum;

NucleotideAlignFoldedDPTable::NucleotideAlignFoldedDPTable(int iLen1,int iLen2) : isInCharge(true), stateId(_NucleotideAlignstateId), emissionId(_NucleotideAlignemissionId), transitionId(_NucleotideAligntransitionId), transitionFrom(_NucleotideAligntransF), transitionTo(_NucleotideAligntransT), transitionProb(_NucleotideAligntransP), transitionEmit(_NucleotideAligntransE), outputId(_NucleotideAlignoutputId) {
    // init code:
    this->iLen1 = iLen1;
    this->iLen2 = iLen2;
    StateMemorynucBlock2.allocate(1+iLen1, 1+iLen2);
    StateMemorynucBlock3.allocate();
    StateMemorynucBlock1.allocate();
}


NucleotideAlignFoldedDPTable::~NucleotideAlignFoldedDPTable() {
    if (!isInCharge) {
        // make sure data does not get deleted:
        StateMemorynucBlock2.absolve();
        StateMemorynucBlock3.absolve();
        StateMemorynucBlock1.absolve();
    } // if(!isInCharge)
} // destructor

const string& NucleotideAlignFoldedDPTable::getTransitionId(int id) { return id>=0 && id<_NucleotideAligntransNum ? _NucleotideAligntransitionId[id] : _NucleotideAlignempty; }
const string& NucleotideAlignFoldedDPTable::getEmissionId(int id) { return id>=0 && id<_NucleotideAlignemitNum ? _NucleotideAlignemissionId[id] : _NucleotideAlignempty; }
const string& NucleotideAlignFoldedDPTable::getStateId(int id) { return id>=0 && id<_NucleotideAlignstateNum ? _NucleotideAlignstateId[id] : _NucleotideAlignempty; }
const string& NucleotideAlignFoldedDPTable::getOutputId(int id) { return id>=0 && id<_NucleotideAlignoutputNum ? _NucleotideAlignoutputId[id] : _NucleotideAlignempty; }
int NucleotideAlignFoldedDPTable::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<_NucleotideAlignstateNum;i++) {
            (*pmId)[_NucleotideAlignstateId[i]] = i;         // add state identifiers
        }
        for (int i=0; i<_NucleotideAlignemitNum; i++) {
            (*pmId)[_NucleotideAlignemissionId[i]] = i;      // add emission identifiers
        }
        for (int i=0; i<_NucleotideAligntransNum; i++) {  
            (*pmId)[_NucleotideAligntransitionId[i]] = i;    // add transition identifiers
        }
        for (int i=0; i<_NucleotideAlignoutputNum; i++) {
            (*pmId)[_NucleotideAlignoutputId[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 << "NucleotideAlignFoldedDPTable::getId: WARNING: identifier '" << sId << "' not found." << endl;
        }
        return -1;
    }
    return iter->second;
}


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


bfloat NucleotideAlignFoldedDPTable::getProb(int iState ,int iPos0,int iPos1) const
{
    const bfloat *CurStateMemorynucBlock1Secondary;
    const bfloat *CurStateMemorynucBlock2Secondary;
    const bfloat *CurStateMemorynucBlock3Secondary;
    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)) {
            CurStateMemorynucBlock1Secondary = this->StateMemorynucBlock1.read();
            return CurStateMemorynucBlock1Secondary[stateTable[iState]];
        } 
        else { 
            return 0.0;
            
        }
        break;
        case 1:
        if ((iPos0+0>=0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=0)&&(iPos1+0<=iLen2+0)) {
            CurStateMemorynucBlock2Secondary = this->StateMemorynucBlock2.read((iPos0-(0))-(0), (iPos1-(0))-(0));
            return CurStateMemorynucBlock2Secondary[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)) {
            CurStateMemorynucBlock3Secondary = this->StateMemorynucBlock3.read();
            return CurStateMemorynucBlock3Secondary[stateTable[iState]];
        } 
        else { 
            return 0.0;
            
        }
    } // switch
} // DPTable...::getProb(int,...)

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


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


void NucleotideAlignBaumWelch::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[_NucleotideAligntransitionId[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[_NucleotideAlignemissionId[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[_NucleotideAlignemissionId[aTemp[i]]] = i;
        }
    }
    for (int i=0; i<1; i++) {
        for(int v10=0;v10<4;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[_NucleotideAlignemissionId[aTemp[i]]] = i;
        }
    }
    for (int i=0; i<1; i++) {
        for(int v00=0;v00<4;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[_NucleotideAlignemissionId[aTemp[i]]] = i;
        }
    }
    for (int i=0; i<1; i++) {
        for(int v00=0;v00<4;v00++)for(int v10=0;v10<4;v10++)
        emissionBaumWelchCount11[v00][v10][i] = 0.0;
    }
    bInited = true;
};


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

void NucleotideAlignBaumWelch::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<4;v10++)
        emissionBaumWelchCount01[v10][i] *= scale;
    }
    for (int i=0; i<1; i++) {
        for(int v00=0;v00<4;v00++)
        emissionBaumWelchCount10[v00][i] *= scale;
    }
    for (int i=0; i<1; i++) {
        for(int v00=0;v00<4;v00++)for(int v10=0;v10<4;v10++)
        emissionBaumWelchCount11[v00][v10][i] *= scale;
    }
}


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

const extern string _NucleotideAlignWithBandingstateId[];
const extern string _NucleotideAlignWithBandingemissionId[];
const extern string _NucleotideAlignWithBandingtransitionId[];
const extern string _NucleotideAlignWithBandingtransF[];
const extern string _NucleotideAlignWithBandingtransT[];
const extern string _NucleotideAlignWithBandingtransP[];
const extern string _NucleotideAlignWithBandingtransE[];
const extern string _NucleotideAlignWithBandingoutputId[];
const extern string _NucleotideAlignWithBandingempty;
const extern int _NucleotideAlignWithBandingstateNum;
const extern int _NucleotideAlignWithBandingemitNum;
const extern int _NucleotideAlignWithBandingtransNum;
const extern int _NucleotideAlignWithBandingoutputNum;

NucleotideAlignWithBandingDPTable::NucleotideAlignWithBandingDPTable(int iLen1,int iLen2) : isInCharge(true), stateId(_NucleotideAlignWithBandingstateId), emissionId(_NucleotideAlignWithBandingemissionId), transitionId(_NucleotideAlignWithBandingtransitionId), transitionFrom(_NucleotideAlignWithBandingtransF), transitionTo(_NucleotideAlignWithBandingtransT), transitionProb(_NucleotideAlignWithBandingtransP), transitionEmit(_NucleotideAlignWithBandingtransE), outputId(_NucleotideAlignWithBandingoutputId) {
    // init code:
    this->iLen1 = iLen1;
    this->iLen2 = iLen2;
    StateMemorynucBlock2withbanding.allocate(1+iLen1, 1+iLen2);
    StateMemorynucBlock1.allocate();
    StateMemorynucBlock3.allocate();
}


NucleotideAlignWithBandingDPTable::~NucleotideAlignWithBandingDPTable() {
    if (!isInCharge) {
        // make sure data does not get deleted:
        StateMemorynucBlock2withbanding.absolve();
        StateMemorynucBlock1.absolve();
        StateMemorynucBlock3.absolve();
    } // if(!isInCharge)
} // destructor

const string& NucleotideAlignWithBandingDPTable::getTransitionId(int id) { return id>=0 && id<_NucleotideAlignWithBandingtransNum ? _NucleotideAlignWithBandingtransitionId[id] : _NucleotideAlignWithBandingempty; }
const string& NucleotideAlignWithBandingDPTable::getEmissionId(int id) { return id>=0 && id<_NucleotideAlignWithBandingemitNum ? _NucleotideAlignWithBandingemissionId[id] : _NucleotideAlignWithBandingempty; }
const string& NucleotideAlignWithBandingDPTable::getStateId(int id) { return id>=0 && id<_NucleotideAlignWithBandingstateNum ? _NucleotideAlignWithBandingstateId[id] : _NucleotideAlignWithBandingempty; }
const string& NucleotideAlignWithBandingDPTable::getOutputId(int id) { return id>=0 && id<_NucleotideAlignWithBandingoutputNum ? _NucleotideAlignWithBandingoutputId[id] : _NucleotideAlignWithBandingempty; }
int NucleotideAlignWithBandingDPTable::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<_NucleotideAlignWithBandingstateNum;i++) {
            (*pmId)[_NucleotideAlignWithBandingstateId[i]] = i;         // add state identifiers
        }
        for (int i=0; i<_NucleotideAlignWithBandingemitNum; i++) {
            (*pmId)[_NucleotideAlignWithBandingemissionId[i]] = i;      // add emission identifiers
        }
        for (int i=0; i<_NucleotideAlignWithBandingtransNum; i++) {  
            (*pmId)[_NucleotideAlignWithBandingtransitionId[i]] = i;    // add transition identifiers
        }
        for (int i=0; i<_NucleotideAlignWithBandingoutputNum; i++) {
            (*pmId)[_NucleotideAlignWithBandingoutputId[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 << "NucleotideAlignWithBandingDPTable::getId: WARNING: identifier '" << sId << "' not found." << endl;
        }
        return -1;
    }
    return iter->second;
}


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


bfloat NucleotideAlignWithBandingDPTable::getProb(int iState ,int iPos0,int iPos1) const
{
    const bfloat *CurStateMemorynucBlock1Secondary;
    const bfloat *CurStateMemorynucBlock2withbandingSecondary;
    const bfloat *CurStateMemorynucBlock3Secondary;
    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)) {
            CurStateMemorynucBlock1Secondary = this->StateMemorynucBlock1.read();
            return CurStateMemorynucBlock1Secondary[stateTable[iState]];
        } 
        else { 
            return 0.0;
            
        }
        break;
        case 1:
        if ((iPos0+0>=0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=0)&&(iPos1+0<=iLen2+0)) {
            CurStateMemorynucBlock2withbandingSecondary = this->StateMemorynucBlock2withbanding.read((iPos0-(0))-(0), (iPos1-(0))-(0));
            return CurStateMemorynucBlock2withbandingSecondary[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)) {
            CurStateMemorynucBlock3Secondary = this->StateMemorynucBlock3.read();
            return CurStateMemorynucBlock3Secondary[stateTable[iState]];
        } 
        else { 
            return 0.0;
            
        }
    } // switch
} // DPTable...::getProb(int,...)

const extern string _NucleotideAlignWithBandingstateId[];
const extern string _NucleotideAlignWithBandingemissionId[];
const extern string _NucleotideAlignWithBandingtransitionId[];
const extern string _NucleotideAlignWithBandingtransF[];
const extern string _NucleotideAlignWithBandingtransT[];
const extern string _NucleotideAlignWithBandingtransP[];
const extern string _NucleotideAlignWithBandingtransE[];
const extern string _NucleotideAlignWithBandingoutputId[];
const extern string _NucleotideAlignWithBandingempty;
const extern int _NucleotideAlignWithBandingstateNum;
const extern int _NucleotideAlignWithBandingemitNum;
const extern int _NucleotideAlignWithBandingtransNum;
const extern int _NucleotideAlignWithBandingoutputNum;

NucleotideAlignWithBandingFoldedDPTable::NucleotideAlignWithBandingFoldedDPTable(int iLen1,int iLen2) : isInCharge(true), stateId(_NucleotideAlignWithBandingstateId), emissionId(_NucleotideAlignWithBandingemissionId), transitionId(_NucleotideAlignWithBandingtransitionId), transitionFrom(_NucleotideAlignWithBandingtransF), transitionTo(_NucleotideAlignWithBandingtransT), transitionProb(_NucleotideAlignWithBandingtransP), transitionEmit(_NucleotideAlignWithBandingtransE), outputId(_NucleotideAlignWithBandingoutputId) {
    // init code:
    this->iLen1 = iLen1;
    this->iLen2 = iLen2;
    StateMemorynucBlock2withbanding.allocate(1+iLen1, 1+iLen2);
    StateMemorynucBlock3.allocate();
    StateMemorynucBlock1.allocate();
}


NucleotideAlignWithBandingFoldedDPTable::~NucleotideAlignWithBandingFoldedDPTable() {
    if (!isInCharge) {
        // make sure data does not get deleted:
        StateMemorynucBlock2withbanding.absolve();
        StateMemorynucBlock3.absolve();
        StateMemorynucBlock1.absolve();
    } // if(!isInCharge)
} // destructor

const string& NucleotideAlignWithBandingFoldedDPTable::getTransitionId(int id) { return id>=0 && id<_NucleotideAlignWithBandingtransNum ? _NucleotideAlignWithBandingtransitionId[id] : _NucleotideAlignWithBandingempty; }
const string& NucleotideAlignWithBandingFoldedDPTable::getEmissionId(int id) { return id>=0 && id<_NucleotideAlignWithBandingemitNum ? _NucleotideAlignWithBandingemissionId[id] : _NucleotideAlignWithBandingempty; }
const string& NucleotideAlignWithBandingFoldedDPTable::getStateId(int id) { return id>=0 && id<_NucleotideAlignWithBandingstateNum ? _NucleotideAlignWithBandingstateId[id] : _NucleotideAlignWithBandingempty; }
const string& NucleotideAlignWithBandingFoldedDPTable::getOutputId(int id) { return id>=0 && id<_NucleotideAlignWithBandingoutputNum ? _NucleotideAlignWithBandingoutputId[id] : _NucleotideAlignWithBandingempty; }
int NucleotideAlignWithBandingFoldedDPTable::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<_NucleotideAlignWithBandingstateNum;i++) {
            (*pmId)[_NucleotideAlignWithBandingstateId[i]] = i;         // add state identifiers
        }
        for (int i=0; i<_NucleotideAlignWithBandingemitNum; i++) {
            (*pmId)[_NucleotideAlignWithBandingemissionId[i]] = i;      // add emission identifiers
        }
        for (int i=0; i<_NucleotideAlignWithBandingtransNum; i++) {  
            (*pmId)[_NucleotideAlignWithBandingtransitionId[i]] = i;    // add transition identifiers
        }
        for (int i=0; i<_NucleotideAlignWithBandingoutputNum; i++) {
            (*pmId)[_NucleotideAlignWithBandingoutputId[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 << "NucleotideAlignWithBandingFoldedDPTable::getId: WARNING: identifier '" << sId << "' not found." << endl;
        }
        return -1;
    }
    return iter->second;
}


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


bfloat NucleotideAlignWithBandingFoldedDPTable::getProb(int iState ,int iPos0,int iPos1) const
{
    const bfloat *CurStateMemorynucBlock1Secondary;
    const bfloat *CurStateMemorynucBlock2withbandingSecondary;
    const bfloat *CurStateMemorynucBlock3Secondary;
    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)) {
            CurStateMemorynucBlock1Secondary = this->StateMemorynucBlock1.read();
            return CurStateMemorynucBlock1Secondary[stateTable[iState]];
        } 
        else { 
            return 0.0;
            
        }
        break;
        case 1:
        if ((iPos0+0>=0)&&(iPos0+0<=iLen1+0)&&(iPos1+0>=0)&&(iPos1+0<=iLen2+0)) {
            CurStateMemorynucBlock2withbandingSecondary = this->StateMemorynucBlock2withbanding.read((iPos0-(0))-(0), (iPos1-(0))-(0));
            return CurStateMemorynucBlock2withbandingSecondary[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)) {
            CurStateMemorynucBlock3Secondary = this->StateMemorynucBlock3.read();
            return CurStateMemorynucBlock3Secondary[stateTable[iState]];
        } 
        else { 
            return 0.0;
            
        }
    } // switch
} // DPTable...::getProb(int,...)

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


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


void NucleotideAlignWithBandingBaumWelch::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[_NucleotideAlignWithBandingtransitionId[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[_NucleotideAlignWithBandingemissionId[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[_NucleotideAlignWithBandingemissionId[aTemp[i]]] = i;
        }
    }
    for (int i=0; i<1; i++) {
        for(int v10=0;v10<4;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[_NucleotideAlignWithBandingemissionId[aTemp[i]]] = i;
        }
    }
    for (int i=0; i<1; i++) {
        for(int v00=0;v00<4;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[_NucleotideAlignWithBandingemissionId[aTemp[i]]] = i;
        }
    }
    for (int i=0; i<1; i++) {
        for(int v00=0;v00<4;v00++)for(int v10=0;v10<4;v10++)
        emissionBaumWelchCount11[v00][v10][i] = 0.0;
    }
    bInited = true;
};


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

void NucleotideAlignWithBandingBaumWelch::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<4;v10++)
        emissionBaumWelchCount01[v10][i] *= scale;
    }
    for (int i=0; i<1; i++) {
        for(int v00=0;v00<4;v00++)
        emissionBaumWelchCount10[v00][i] *= scale;
    }
    for (int i=0; i<1; i++) {
        for(int v00=0;v00<4;v00++)for(int v10=0;v10<4;v10++)
        emissionBaumWelchCount11[v00][v10][i] *= scale;
    }
}


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

const string _NucleotideAlignstateId[] = {"start","insert1","match","delete1","end"};
const string _NucleotideAlignemissionId[] = {"emit12","emit2","empty","emit1"};
const string _NucleotideAligntransitionId[] = {"trSM","trSI1","trSD1","trMM","trMI1","trMD1","trME","trI1M","trI1I1","trI1E","trD1M","trD1D1","trD1E"};
const string _NucleotideAligntransF[] = {"start","start","start","match","match","match","match","insert1","insert1","insert1","delete1","delete1","delete1"};
const string _NucleotideAligntransT[] = {"match","insert1","delete1","match","insert1","delete1","end","match","insert1","end","match","delete1","end"};
const string _NucleotideAligntransP[] = {"probSM","probSI1","probSD1","probMM","probMI1","probMD1","probME","probI1M","probI1I1","probI1E","probD1M","probD1D1","probD1E"};
const string _NucleotideAligntransE[] = {"emit12","emit1","emit2","emit12","emit1","emit2","empty","emit12","emit1","empty","emit12","emit2","empty"};
const string _NucleotideAlignoutputId[] = {"sequence1","sequence2"};
const string _NucleotideAlignempty = "";
const int _NucleotideAlignstateNum = 5;
const int _NucleotideAlignemitNum = 4;
const int _NucleotideAligntransNum = 13;
const int _NucleotideAlignoutputNum = 2;




bfloat Forward(NucleotideAlignDPTable** 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 *CurStateMemorynucBlock2To;
    const bfloat *CurStateMemorynucBlock1From;
    const bfloat *CurStateMemorynucBlock2From;
    bfloat *CurStateMemorynucBlock3To;
    const bfloat *CurStateMemorynucBlock3From;
    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)'G'] = 2;
    iTranslate[(unsigned)'g'] = 2;
    iTranslate[(unsigned)'T'] = 3;
    iTranslate[(unsigned)'t'] = 3;
    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];
    NucleotideAlignDPTable 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.StateMemorynucBlock1.write()[0] = 1.0;
    dp.StateMemorynucBlock1.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 */;
                    
                }
                CurStateMemorynucBlock2To = dp.StateMemorynucBlock2.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)) {
                    CurStateMemorynucBlock1From = dp.StateMemorynucBlock1.read();
                    CurStateMemorynucBlock2To[2] = ((iTransition[2])*(iEmission[0]))*CurStateMemorynucBlock1From[0];
                }
                if ((iPos1+-1>=0)) {
                    CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(0))-(0), (iPos1-(1))-(0));
                    CurStateMemorynucBlock2To[2] += ((iTransition[5])*(iEmission[0]))*CurStateMemorynucBlock2From[1];
                    CurStateMemorynucBlock2To[2] += ((iTransition[11])*(iEmission[0]))*CurStateMemorynucBlock2From[2];
                }
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+-1>=0)&&(iPos0+-1<=0)&&(iPos1+0<=0)) {
                    CurStateMemorynucBlock1From = dp.StateMemorynucBlock1.read();
                    CurStateMemorynucBlock2To[0] = ((iTransition[1])*(iEmission[0]))*CurStateMemorynucBlock1From[0];
                }
                if ((iPos0+-1>=0)) {
                    CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(1))-(0), (iPos1-(0))-(0));
                    CurStateMemorynucBlock2To[0] += ((iTransition[4])*(iEmission[0]))*CurStateMemorynucBlock2From[1];
                    CurStateMemorynucBlock2To[0] += ((iTransition[8])*(iEmission[0]))*CurStateMemorynucBlock2From[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)) {
                    CurStateMemorynucBlock1From = dp.StateMemorynucBlock1.read();
                    CurStateMemorynucBlock2To[1] = ((iTransition[0])*(iEmission[0]))*CurStateMemorynucBlock1From[0];
                }
                if ((iPos0+-1>=0)&&(iPos1+-1>=0)) {
                    CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(1))-(0), (iPos1-(1))-(0));
                    CurStateMemorynucBlock2To[1] += ((iTransition[3])*(iEmission[0]))*CurStateMemorynucBlock2From[1];
                    CurStateMemorynucBlock2To[1] += ((iTransition[7])*(iEmission[0]))*CurStateMemorynucBlock2From[0];
                    CurStateMemorynucBlock2To[1] += ((iTransition[10])*(iEmission[0]))*CurStateMemorynucBlock2From[2];
                }
                dp.StateMemorynucBlock2.written();
            }
            if ((iPos0+0>=iLen1+0)&&(iPos1+0>=iLen2+0)) {
                CurStateMemorynucBlock3To = dp.StateMemorynucBlock3.write();
                iEmission[0] = 1.0;
                if (1) {
                    CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(0))-(0), (iPos1-(0))-(0));
                    CurStateMemorynucBlock3To[0] = ((iTransition[6])*(iEmission[0]))*CurStateMemorynucBlock2From[1];
                    CurStateMemorynucBlock3To[0] += ((iTransition[9])*(iEmission[0]))*CurStateMemorynucBlock2From[0];
                    CurStateMemorynucBlock3To[0] += ((iTransition[12])*(iEmission[0]))*CurStateMemorynucBlock2From[2];
                }
                dp.StateMemorynucBlock3.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
            CurStateMemorynucBlock3From = dp.StateMemorynucBlock3.read();
            iTempProb[0] = CurStateMemorynucBlock3From[0];
        }
    }
    *ppOutTable = new NucleotideAlignDPTable(dp);
    // make sure tables don't get deleted
    dp.isInCharge = false;
    return iTempProb[0];
};





bfloat BackwardBaumWelch(NucleotideAlignBaumWelch& bw,NucleotideAlignDPTable* 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 *CurStateMemorynucBlock3Secondary;
    bfloat iTransition[13];
    bfloat *CurStateMemorynucBlock2To;
    const bfloat *CurStateMemorynucBlock2Secondary;
    const bfloat *CurStateMemorynucBlock2From;
    unsigned char alphaSymbolnucleotide[4] = {'A', 'C', 'G', 'T'};
    unsigned char alphaIndexnucleotide[256];
    const bfloat *CurStateMemorynucBlock3From;
    bfloat *CurStateMemorynucBlock1To;
    const bfloat *CurStateMemorynucBlock1Secondary;
    const bfloat *CurStateMemorynucBlock1From;
    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)'G'] = 2;
    iTranslate[(unsigned)'g'] = 2;
    iTranslate[(unsigned)'T'] = 3;
    iTranslate[(unsigned)'t'] = 3;
    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];
    NucleotideAlignFoldedDPTable dp(iLen1,2);
    NucleotideAlignDPTable 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++) {
        alphaIndexnucleotide[i]=0;
    }

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

    dp.StateMemorynucBlock3.write()[0] = 1.0;
    dp.StateMemorynucBlock3.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
            CurStateMemorynucBlock3Secondary = dp2.StateMemorynucBlock3.read();
            iTempProb[2] = CurStateMemorynucBlock3Secondary[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.StateMemorynucBlock2.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 */;
                    
                }
                CurStateMemorynucBlock2To = dp.StateMemorynucBlock2.write((iPos0-(0))-(0), (iPos1-(0))-(0));
                CurStateMemorynucBlock2Secondary = dp2.StateMemorynucBlock2.read((iPos0-(0))-(0), (iPos1-(0))-(0));
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos1+1<=iLen2+0)) {
                    CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
                    CurStateMemorynucBlock2To[2] = iTempProb[1] = ((iTransition[11])*(iEmission[0]))*CurStateMemorynucBlock2From[2];
                    iTempProb[1] *= CurStateMemorynucBlock2Secondary[2];
                    bw.transitionBaumWelchCount00[11] += iTempProb[1];
                    bw.emissionBaumWelchCount01[alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
                    CurStateMemorynucBlock2To[1] = iTempProb[1] = ((iTransition[5])*(iEmission[0]))*CurStateMemorynucBlock2From[2];
                    iTempProb[1] *= CurStateMemorynucBlock2Secondary[1];
                    bw.transitionBaumWelchCount00[5] += iTempProb[1];
                    bw.emissionBaumWelchCount01[alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
                }
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+1<=iLen1+0)) {
                    CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
                    CurStateMemorynucBlock2To[0] = iTempProb[1] = ((iTransition[8])*(iEmission[0]))*CurStateMemorynucBlock2From[0];
                    iTempProb[1] *= CurStateMemorynucBlock2Secondary[0];
                    bw.transitionBaumWelchCount00[8] += iTempProb[1];
                    bw.emissionBaumWelchCount10[alphaIndexnucleotide[iSymbol[1]]][0] += iTempProb[1];
                    CurStateMemorynucBlock2To[1] += iTempProb[1] = ((iTransition[4])*(iEmission[0]))*CurStateMemorynucBlock2From[0];
                    iTempProb[1] *= CurStateMemorynucBlock2Secondary[1];
                    bw.transitionBaumWelchCount00[4] += iTempProb[1];
                    bw.emissionBaumWelchCount10[alphaIndexnucleotide[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)) {
                    CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
                    CurStateMemorynucBlock2To[2] += iTempProb[1] = ((iTransition[10])*(iEmission[0]))*CurStateMemorynucBlock2From[1];
                    iTempProb[1] *= CurStateMemorynucBlock2Secondary[2];
                    bw.transitionBaumWelchCount00[10] += iTempProb[1];
                    bw.emissionBaumWelchCount11[alphaIndexnucleotide[iSymbol[1]]][alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
                    CurStateMemorynucBlock2To[0] += iTempProb[1] = ((iTransition[7])*(iEmission[0]))*CurStateMemorynucBlock2From[1];
                    iTempProb[1] *= CurStateMemorynucBlock2Secondary[0];
                    bw.transitionBaumWelchCount00[7] += iTempProb[1];
                    bw.emissionBaumWelchCount11[alphaIndexnucleotide[iSymbol[1]]][alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
                    CurStateMemorynucBlock2To[1] += iTempProb[1] = ((iTransition[3])*(iEmission[0]))*CurStateMemorynucBlock2From[1];
                    iTempProb[1] *= CurStateMemorynucBlock2Secondary[1];
                    bw.transitionBaumWelchCount00[3] += iTempProb[1];
                    bw.emissionBaumWelchCount11[alphaIndexnucleotide[iSymbol[1]]][alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
                }
                iEmission[0] = 1.0;
                if ((iPos0+0>=iLen1+0)&&(iPos1+0>=iLen2+0)) {
                    CurStateMemorynucBlock3From = dp.StateMemorynucBlock3.read();
                    CurStateMemorynucBlock2To[2] += iTempProb[1] = ((iTransition[12])*(iEmission[0]))*CurStateMemorynucBlock3From[0];
                    iTempProb[1] *= CurStateMemorynucBlock2Secondary[2];
                    bw.transitionBaumWelchCount00[12] += iTempProb[1];
                    bw.emissionBaumWelchCount00[0] += iTempProb[1];
                    CurStateMemorynucBlock2To[0] += iTempProb[1] = ((iTransition[9])*(iEmission[0]))*CurStateMemorynucBlock3From[0];
                    iTempProb[1] *= CurStateMemorynucBlock2Secondary[0];
                    bw.transitionBaumWelchCount00[9] += iTempProb[1];
                    bw.emissionBaumWelchCount00[0] += iTempProb[1];
                    CurStateMemorynucBlock2To[1] += iTempProb[1] = ((iTransition[6])*(iEmission[0]))*CurStateMemorynucBlock3From[0];
                    iTempProb[1] *= CurStateMemorynucBlock2Secondary[1];
                    bw.transitionBaumWelchCount00[6] += iTempProb[1];
                    bw.emissionBaumWelchCount00[0] += iTempProb[1];
                }
                dp.StateMemorynucBlock2.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 */;
                    
                }
                CurStateMemorynucBlock1To = dp.StateMemorynucBlock1.write();
                CurStateMemorynucBlock1Secondary = dp2.StateMemorynucBlock1.read();
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos1+1<=iLen2+0)) {
                    CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
                    CurStateMemorynucBlock1To[0] = iTempProb[1] = ((iTransition[2])*(iEmission[0]))*CurStateMemorynucBlock2From[2];
                    iTempProb[1] *= CurStateMemorynucBlock1Secondary[0];
                    bw.transitionBaumWelchCount00[2] += iTempProb[1];
                    bw.emissionBaumWelchCount01[alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
                }
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+1<=iLen1+0)) {
                    CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
                    CurStateMemorynucBlock1To[0] += iTempProb[1] = ((iTransition[1])*(iEmission[0]))*CurStateMemorynucBlock2From[0];
                    iTempProb[1] *= CurStateMemorynucBlock1Secondary[0];
                    bw.transitionBaumWelchCount00[1] += iTempProb[1];
                    bw.emissionBaumWelchCount10[alphaIndexnucleotide[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)) {
                    CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
                    CurStateMemorynucBlock1To[0] += iTempProb[1] = ((iTransition[0])*(iEmission[0]))*CurStateMemorynucBlock2From[1];
                    iTempProb[1] *= CurStateMemorynucBlock1Secondary[0];
                    bw.transitionBaumWelchCount00[0] += iTempProb[1];
                    bw.emissionBaumWelchCount11[alphaIndexnucleotide[iSymbol[1]]][alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
                }
                dp.StateMemorynucBlock1.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
            CurStateMemorynucBlock1From = dp.StateMemorynucBlock1.read();
            iTempProb[0] = CurStateMemorynucBlock1From[0];
        }
    }
    return iTempProb[0];
};





bfloat Backward(NucleotideAlignDPTable** 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 *CurStateMemorynucBlock2To;
    const bfloat *CurStateMemorynucBlock2From;
    const bfloat *CurStateMemorynucBlock3From;
    bfloat *CurStateMemorynucBlock1To;
    const bfloat *CurStateMemorynucBlock1From;
    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)'G'] = 2;
    iTranslate[(unsigned)'g'] = 2;
    iTranslate[(unsigned)'T'] = 3;
    iTranslate[(unsigned)'t'] = 3;
    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];
    NucleotideAlignDPTable 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.StateMemorynucBlock3.write()[0] = 1.0;
    dp.StateMemorynucBlock3.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 */;
                    
                }
                CurStateMemorynucBlock2To = dp.StateMemorynucBlock2.write((iPos0-(0))-(0), (iPos1-(0))-(0));
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos1+1<=iLen2+0)) {
                    CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
                    CurStateMemorynucBlock2To[2] = ((iTransition[11])*(iEmission[0]))*CurStateMemorynucBlock2From[2];
                    CurStateMemorynucBlock2To[1] = ((iTransition[5])*(iEmission[0]))*CurStateMemorynucBlock2From[2];
                }
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+1<=iLen1+0)) {
                    CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
                    CurStateMemorynucBlock2To[0] = ((iTransition[8])*(iEmission[0]))*CurStateMemorynucBlock2From[0];
                    CurStateMemorynucBlock2To[1] += ((iTransition[4])*(iEmission[0]))*CurStateMemorynucBlock2From[0];
                }
                iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
                    CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
                    CurStateMemorynucBlock2To[2] += ((iTransition[10])*(iEmission[0]))*CurStateMemorynucBlock2From[1];
                    CurStateMemorynucBlock2To[0] += ((iTransition[7])*(iEmission[0]))*CurStateMemorynucBlock2From[1];
                    CurStateMemorynucBlock2To[1] += ((iTransition[3])*(iEmission[0]))*CurStateMemorynucBlock2From[1];
                }
                iEmission[0] = 1.0;
                if ((iPos0+0>=iLen1+0)&&(iPos1+0>=iLen2+0)) {
                    CurStateMemorynucBlock3From = dp.StateMemorynucBlock3.read();
                    CurStateMemorynucBlock2To[2] += ((iTransition[12])*(iEmission[0]))*CurStateMemorynucBlock3From[0];
                    CurStateMemorynucBlock2To[0] += ((iTransition[9])*(iEmission[0]))*CurStateMemorynucBlock3From[0];
                    CurStateMemorynucBlock2To[1] += ((iTransition[6])*(iEmission[0]))*CurStateMemorynucBlock3From[0];
                }
                dp.StateMemorynucBlock2.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 */;
                    
                }
                CurStateMemorynucBlock1To = dp.StateMemorynucBlock1.write();
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos1+1<=iLen2+0)) {
                    CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
                    CurStateMemorynucBlock1To[0] = ((iTransition[2])*(iEmission[0]))*CurStateMemorynucBlock2From[2];
                }
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+1<=iLen1+0)) {
                    CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
                    CurStateMemorynucBlock1To[0] += ((iTransition[1])*(iEmission[0]))*CurStateMemorynucBlock2From[0];
                }
                iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
                    CurStateMemorynucBlock2From = dp.StateMemorynucBlock2.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
                    CurStateMemorynucBlock1To[0] += ((iTransition[0])*(iEmission[0]))*CurStateMemorynucBlock2From[1];
                }
                dp.StateMemorynucBlock1.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
            CurStateMemorynucBlock1From = dp.StateMemorynucBlock1.read();
            iTempProb[0] = CurStateMemorynucBlock1From[0];
        }
    }
    *ppOutTable = new NucleotideAlignDPTable(dp);
    // make sure tables don't get deleted
    dp.isInCharge = false;
    return iTempProb[0];
};



const string _NucleotideAlignWithBandingstateId[] = {"start","insert1","match","delete1","end"};
const string _NucleotideAlignWithBandingemissionId[] = {"emit12","emit2","empty","emit1"};
const string _NucleotideAlignWithBandingtransitionId[] = {"trSM","trSI1","trSD1","trMM","trMI1","trMD1","trME","trI1M","trI1I1","trI1E","trD1M","trD1D1","trD1E"};
const string _NucleotideAlignWithBandingtransF[] = {"start","start","start","match","match","match","match","insert1","insert1","insert1","delete1","delete1","delete1"};
const string _NucleotideAlignWithBandingtransT[] = {"match","insert1","delete1","match","insert1","delete1","end","match","insert1","end","match","delete1","end"};
const string _NucleotideAlignWithBandingtransP[] = {"probSM","probSI1","probSD1","probMM","probMI1","probMD1","probME","probI1M","probI1I1","probI1E","probD1M","probD1D1","probD1E"};
const string _NucleotideAlignWithBandingtransE[] = {"emit12","emit1","emit2","emit12","emit1","emit2","empty","emit12","emit1","empty","emit12","emit2","empty"};
const string _NucleotideAlignWithBandingoutputId[] = {"sequence1","sequence2"};
const string _NucleotideAlignWithBandingempty = "";
const int _NucleotideAlignWithBandingstateNum = 5;
const int _NucleotideAlignWithBandingemitNum = 4;
const int _NucleotideAlignWithBandingtransNum = 13;
const int _NucleotideAlignWithBandingoutputNum = 2;




bfloat ForwardBanding(NucleotideAlignWithBandingDPTable** 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 *CurStateMemorynucBlock2withbandingTo;
    const bfloat *CurStateMemorynucBlock1From;
    const bfloat *CurStateMemorynucBlock2withbandingFrom;
    bfloat *CurStateMemorynucBlock3To;
    const bfloat *CurStateMemorynucBlock3From;
    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)'G'] = 2;
    iTranslate[(unsigned)'g'] = 2;
    iTranslate[(unsigned)'T'] = 3;
    iTranslate[(unsigned)'t'] = 3;
    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];
    NucleotideAlignWithBandingDPTable 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.StateMemorynucBlock1.write()[0] = 1.0;
    dp.StateMemorynucBlock1.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 */;
                        
                    }
                    CurStateMemorynucBlock2withbandingTo = dp.StateMemorynucBlock2withbanding.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)) {
                        CurStateMemorynucBlock1From = dp.StateMemorynucBlock1.read();
                        CurStateMemorynucBlock2withbandingTo[2] = ((iTransition[2])*(iEmission[0]))*CurStateMemorynucBlock1From[0];
                    }
                    if ((position[1]+-1>=0)) {
                        CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((position[0]-(0))-(0), (position[1]-(1))-(0));
                        CurStateMemorynucBlock2withbandingTo[2] += ((iTransition[11])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[2];
                        CurStateMemorynucBlock2withbandingTo[2] += ((iTransition[5])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[1];
                    }
                    iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
                    iEmission[0] = iTempResult[0];
                    if ((position[0]+-1>=0)&&(position[0]+-1<=0)&&(position[1]+0<=0)) {
                        CurStateMemorynucBlock1From = dp.StateMemorynucBlock1.read();
                        CurStateMemorynucBlock2withbandingTo[0] = ((iTransition[1])*(iEmission[0]))*CurStateMemorynucBlock1From[0];
                    }
                    if ((position[0]+-1>=0)) {
                        CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((position[0]-(1))-(0), (position[1]-(0))-(0));
                        CurStateMemorynucBlock2withbandingTo[0] += ((iTransition[4])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[1];
                        CurStateMemorynucBlock2withbandingTo[0] += ((iTransition[8])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[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)) {
                        CurStateMemorynucBlock1From = dp.StateMemorynucBlock1.read();
                        CurStateMemorynucBlock2withbandingTo[1] = ((iTransition[0])*(iEmission[0]))*CurStateMemorynucBlock1From[0];
                    }
                    if ((position[0]+-1>=0)&&(position[1]+-1>=0)) {
                        CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((position[0]-(1))-(0), (position[1]-(1))-(0));
                        CurStateMemorynucBlock2withbandingTo[1] += ((iTransition[10])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[2];
                        CurStateMemorynucBlock2withbandingTo[1] += ((iTransition[3])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[1];
                        CurStateMemorynucBlock2withbandingTo[1] += ((iTransition[7])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[0];
                    }
                    dp.StateMemorynucBlock2withbanding.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) {
                CurStateMemorynucBlock3To = dp.StateMemorynucBlock3.write();
                iEmission[0] = 1.0;
                if (1) {
                    CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((iPos0-(0))-(0), (iPos1-(0))-(0));
                    CurStateMemorynucBlock3To[0] = ((iTransition[12])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[2];
                    CurStateMemorynucBlock3To[0] += ((iTransition[6])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[1];
                    CurStateMemorynucBlock3To[0] += ((iTransition[9])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[0];
                }
                dp.StateMemorynucBlock3.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
            CurStateMemorynucBlock3From = dp.StateMemorynucBlock3.read();
            iTempProb[0] = CurStateMemorynucBlock3From[0];
        }
    }
    *ppOutTable = new NucleotideAlignWithBandingDPTable(dp);
    // make sure tables don't get deleted
    dp.isInCharge = false;
    return iTempProb[0];
};





bfloat BackwardBaumWelchBanding(NucleotideAlignWithBandingBaumWelch& bw,NucleotideAlignWithBandingDPTable* 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 *CurStateMemorynucBlock3Secondary;
    bfloat iTransition[13];
    bfloat *CurStateMemorynucBlock2withbandingTo;
    const bfloat *CurStateMemorynucBlock2withbandingSecondary;
    const bfloat *CurStateMemorynucBlock2withbandingFrom;
    unsigned char alphaSymbolnucleotide[4] = {'A', 'C', 'G', 'T'};
    unsigned char alphaIndexnucleotide[256];
    const bfloat *CurStateMemorynucBlock3From;
    bfloat *CurStateMemorynucBlock1To;
    const bfloat *CurStateMemorynucBlock1Secondary;
    const bfloat *CurStateMemorynucBlock1From;
    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)'G'] = 2;
    iTranslate[(unsigned)'g'] = 2;
    iTranslate[(unsigned)'T'] = 3;
    iTranslate[(unsigned)'t'] = 3;
    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];
    NucleotideAlignWithBandingFoldedDPTable dp(iLen1,2);
    NucleotideAlignWithBandingDPTable 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++) {
        alphaIndexnucleotide[i]=0;
    }

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

    dp.StateMemorynucBlock3.write()[0] = 1.0;
    dp.StateMemorynucBlock3.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
            CurStateMemorynucBlock3Secondary = dp2.StateMemorynucBlock3.read();
            iTempProb[2] = CurStateMemorynucBlock3Secondary[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.StateMemorynucBlock2withbanding.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 */;
                        
                    }
                    CurStateMemorynucBlock2withbandingTo = dp.StateMemorynucBlock2withbanding.write((position[0]-(0))-(0), (position[1]-(0))-(0));
                    CurStateMemorynucBlock2withbandingSecondary = dp2.StateMemorynucBlock2withbanding.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)) {
                        CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((position[0]-(0))-(0), (position[1]-(-1))-(0));
                        CurStateMemorynucBlock2withbandingTo[2] = iTempProb[1] = ((iTransition[11])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[2];
                        iTempProb[1] *= CurStateMemorynucBlock2withbandingSecondary[2];
                        bw.transitionBaumWelchCount00[11] += iTempProb[1];
                        bw.emissionBaumWelchCount01[alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
                        CurStateMemorynucBlock2withbandingTo[1] = iTempProb[1] = ((iTransition[5])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[2];
                        iTempProb[1] *= CurStateMemorynucBlock2withbandingSecondary[1];
                        bw.transitionBaumWelchCount00[5] += iTempProb[1];
                        bw.emissionBaumWelchCount01[alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
                    }
                    iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
                    iEmission[0] = iTempResult[0];
                    if ((position[0]+1<=iLen1+0)) {
                        CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((position[0]-(-1))-(0), (position[1]-(0))-(0));
                        CurStateMemorynucBlock2withbandingTo[1] += iTempProb[1] = ((iTransition[4])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[0];
                        iTempProb[1] *= CurStateMemorynucBlock2withbandingSecondary[1];
                        bw.transitionBaumWelchCount00[4] += iTempProb[1];
                        bw.emissionBaumWelchCount10[alphaIndexnucleotide[iSymbol[1]]][0] += iTempProb[1];
                        CurStateMemorynucBlock2withbandingTo[0] = iTempProb[1] = ((iTransition[8])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[0];
                        iTempProb[1] *= CurStateMemorynucBlock2withbandingSecondary[0];
                        bw.transitionBaumWelchCount00[8] += iTempProb[1];
                        bw.emissionBaumWelchCount10[alphaIndexnucleotide[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)) {
                        CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((position[0]-(-1))-(0), (position[1]-(-1))-(0));
                        CurStateMemorynucBlock2withbandingTo[2] += iTempProb[1] = ((iTransition[10])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[1];
                        iTempProb[1] *= CurStateMemorynucBlock2withbandingSecondary[2];
                        bw.transitionBaumWelchCount00[10] += iTempProb[1];
                        bw.emissionBaumWelchCount11[alphaIndexnucleotide[iSymbol[1]]][alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
                        CurStateMemorynucBlock2withbandingTo[1] += iTempProb[1] = ((iTransition[3])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[1];
                        iTempProb[1] *= CurStateMemorynucBlock2withbandingSecondary[1];
                        bw.transitionBaumWelchCount00[3] += iTempProb[1];
                        bw.emissionBaumWelchCount11[alphaIndexnucleotide[iSymbol[1]]][alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
                        CurStateMemorynucBlock2withbandingTo[0] += iTempProb[1] = ((iTransition[7])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[1];
                        iTempProb[1] *= CurStateMemorynucBlock2withbandingSecondary[0];
                        bw.transitionBaumWelchCount00[7] += iTempProb[1];
                        bw.emissionBaumWelchCount11[alphaIndexnucleotide[iSymbol[1]]][alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
                    }
                    iEmission[0] = 1.0;
                    if ((position[0]+0>=iLen1+0)&&(position[1]+0>=iLen2+0)) {
                        CurStateMemorynucBlock3From = dp.StateMemorynucBlock3.read();
                        CurStateMemorynucBlock2withbandingTo[2] += iTempProb[1] = ((iTransition[12])*(iEmission[0]))*CurStateMemorynucBlock3From[0];
                        iTempProb[1] *= CurStateMemorynucBlock2withbandingSecondary[2];
                        bw.transitionBaumWelchCount00[12] += iTempProb[1];
                        bw.emissionBaumWelchCount00[0] += iTempProb[1];
                        CurStateMemorynucBlock2withbandingTo[1] += iTempProb[1] = ((iTransition[6])*(iEmission[0]))*CurStateMemorynucBlock3From[0];
                        iTempProb[1] *= CurStateMemorynucBlock2withbandingSecondary[1];
                        bw.transitionBaumWelchCount00[6] += iTempProb[1];
                        bw.emissionBaumWelchCount00[0] += iTempProb[1];
                        CurStateMemorynucBlock2withbandingTo[0] += iTempProb[1] = ((iTransition[9])*(iEmission[0]))*CurStateMemorynucBlock3From[0];
                        iTempProb[1] *= CurStateMemorynucBlock2withbandingSecondary[0];
                        bw.transitionBaumWelchCount00[9] += iTempProb[1];
                        bw.emissionBaumWelchCount00[0] += iTempProb[1];
                    }
                    dp.StateMemorynucBlock2withbanding.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 */;
                    
                }
                CurStateMemorynucBlock1To = dp.StateMemorynucBlock1.write();
                CurStateMemorynucBlock1Secondary = dp2.StateMemorynucBlock1.read();
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos1+1<=iLen2+0)) {
                    CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
                    CurStateMemorynucBlock1To[0] = iTempProb[1] = ((iTransition[2])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[2];
                    iTempProb[1] *= CurStateMemorynucBlock1Secondary[0];
                    bw.transitionBaumWelchCount00[2] += iTempProb[1];
                    bw.emissionBaumWelchCount01[alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
                }
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+1<=iLen1+0)) {
                    CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
                    CurStateMemorynucBlock1To[0] += iTempProb[1] = ((iTransition[1])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[0];
                    iTempProb[1] *= CurStateMemorynucBlock1Secondary[0];
                    bw.transitionBaumWelchCount00[1] += iTempProb[1];
                    bw.emissionBaumWelchCount10[alphaIndexnucleotide[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)) {
                    CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
                    CurStateMemorynucBlock1To[0] += iTempProb[1] = ((iTransition[0])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[1];
                    iTempProb[1] *= CurStateMemorynucBlock1Secondary[0];
                    bw.transitionBaumWelchCount00[0] += iTempProb[1];
                    bw.emissionBaumWelchCount11[alphaIndexnucleotide[iSymbol[1]]][alphaIndexnucleotide[iSymbol[0]]][0] += iTempProb[1];
                }
                dp.StateMemorynucBlock1.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
            CurStateMemorynucBlock1From = dp.StateMemorynucBlock1.read();
            iTempProb[0] = CurStateMemorynucBlock1From[0];
        }
    }
    return iTempProb[0];
};





bfloat BackwardBanding(NucleotideAlignWithBandingDPTable** 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 *CurStateMemorynucBlock2withbandingTo;
    const bfloat *CurStateMemorynucBlock2withbandingFrom;
    const bfloat *CurStateMemorynucBlock3From;
    bfloat *CurStateMemorynucBlock1To;
    const bfloat *CurStateMemorynucBlock1From;
    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)'G'] = 2;
    iTranslate[(unsigned)'g'] = 2;
    iTranslate[(unsigned)'T'] = 3;
    iTranslate[(unsigned)'t'] = 3;
    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];
    NucleotideAlignWithBandingDPTable 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.StateMemorynucBlock3.write()[0] = 1.0;
    dp.StateMemorynucBlock3.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 */;
                        
                    }
                    CurStateMemorynucBlock2withbandingTo = dp.StateMemorynucBlock2withbanding.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)) {
                        CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((position[0]-(0))-(0), (position[1]-(-1))-(0));
                        CurStateMemorynucBlock2withbandingTo[1] = ((iTransition[5])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[2];
                        CurStateMemorynucBlock2withbandingTo[2] = ((iTransition[11])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[2];
                    }
                    iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
                    iEmission[0] = iTempResult[0];
                    if ((position[0]+1<=iLen1+0)) {
                        CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((position[0]-(-1))-(0), (position[1]-(0))-(0));
                        CurStateMemorynucBlock2withbandingTo[1] += ((iTransition[4])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[0];
                        CurStateMemorynucBlock2withbandingTo[0] = ((iTransition[8])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[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)) {
                        CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((position[0]-(-1))-(0), (position[1]-(-1))-(0));
                        CurStateMemorynucBlock2withbandingTo[2] += ((iTransition[10])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[1];
                        CurStateMemorynucBlock2withbandingTo[1] += ((iTransition[3])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[1];
                        CurStateMemorynucBlock2withbandingTo[0] += ((iTransition[7])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[1];
                    }
                    iEmission[0] = 1.0;
                    if ((position[0]+0>=iLen1+0)&&(position[1]+0>=iLen2+0)) {
                        CurStateMemorynucBlock3From = dp.StateMemorynucBlock3.read();
                        CurStateMemorynucBlock2withbandingTo[2] += ((iTransition[12])*(iEmission[0]))*CurStateMemorynucBlock3From[0];
                        CurStateMemorynucBlock2withbandingTo[1] += ((iTransition[6])*(iEmission[0]))*CurStateMemorynucBlock3From[0];
                        CurStateMemorynucBlock2withbandingTo[0] += ((iTransition[9])*(iEmission[0]))*CurStateMemorynucBlock3From[0];
                    }
                    dp.StateMemorynucBlock2withbanding.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 */;
                    
                }
                CurStateMemorynucBlock1To = dp.StateMemorynucBlock1.write();
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos1+1<=iLen2+0)) {
                    CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((iPos0-(0))-(0), (iPos1-(-1))-(0));
                    CurStateMemorynucBlock1To[0] = ((iTransition[2])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[2];
                }
                iTempResult[0] = iSingleDistribution[iTranslate[iSymbol[1]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+1<=iLen1+0)) {
                    CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((iPos0-(-1))-(0), (iPos1-(0))-(0));
                    CurStateMemorynucBlock1To[0] += ((iTransition[1])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[0];
                }
                iTempResult[0] = iPairDistribution[iTranslate[iSymbol[1]]][iTranslate[iSymbol[0]]];
                iEmission[0] = iTempResult[0];
                if ((iPos0+1<=iLen1+0)&&(iPos1+1<=iLen2+0)) {
                    CurStateMemorynucBlock2withbandingFrom = dp.StateMemorynucBlock2withbanding.read((iPos0-(-1))-(0), (iPos1-(-1))-(0));
                    CurStateMemorynucBlock1To[0] += ((iTransition[0])*(iEmission[0]))*CurStateMemorynucBlock2withbandingFrom[1];
                }
                dp.StateMemorynucBlock1.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
            CurStateMemorynucBlock1From = dp.StateMemorynucBlock1.read();
            iTempProb[0] = CurStateMemorynucBlock1From[0];
        }
    }
    *ppOutTable = new NucleotideAlignWithBandingDPTable(dp);
    // make sure tables don't get deleted
    dp.isInCharge = false;
    return iTempProb[0];
};



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