// ART1MASPAR.cpp
// (c) Indra's Net Farm - 2002
// trans(c) Tim McFadden
// This code is released to be used entirely at the user's own risk
// for any consequences what so ever.
// Please keep the Indra's Net Farm name on copied code.

#include <iostream>
#include "ART1MASPAR.h"
#include "Up.h"

void ART1_Interfac(char* filenam);

//
// ART1MASPAR() - main class for application.
// reads in parameters, creates objects, and runs
// the main processing loop.
//

ART1MASPAR::ART1MASPAR(char* filenam)
{

int i,j,k;

int traceIndx; // index thru traces.

int reset = 0; // 1 => a F1 calls for a reset of F2.

int wini; // the index of the winning node in F2.

int loopCnt; // count of loops thru a resonance.


// dummy values for compiler.

M = 30;

N = 30;

L = 0;

B1 = 0;

D1 = 0;

rho = 0;

BotupFact = 0;

if (DebugFlag >= 1)

cout << "ART1MASPAR\n";

// create array for input patterns.

inPuts = new int [maxInputs] [maxM] ;


// read in ART1 params.

Parse.parse(this, filenam);

if (DebugFlag >= 1)

{

cout << "parser read " << rowCnt << " traces \n";

cout << "create the objects\n";\

}


// create the objects.

// F1 and F2 layers.

F1L = Fact.Make1(N, A1, B1, C1, D1, DebugFlag);

F2L = Fact.Make2(M, DebugFlag);


// shared registers.

F2L->VReg = F1L->VReg = new FloatReg(N);

F2L->TReg = F1L->TReg = new FloatReg(M);

F1L->IReg = new IntReg(N);


// LTM.

F1L->LTMBU = new LTMBottomUp(N, M, L, BotupFact, DebugFlag);

F2L->LTMTD = new LTMTopDown(N, M, B1, D1, DebugFlag);


// orienting subsystem, used by F1.

F1L->Ori = new Orienting(rho, N);


if (DebugFlag >= 1)

{

// dump LTM.

cout << "Initial LTM\nZbu " "\n";

F1L->LTMBU->dump();

cout << "Ztd " "\n";

F2L->LTMTD->dump();

}

}

//

// ART1MASPAR::run() - run resonance.

void ART1MASPAR::run() {

int i,j,k;

int traceIndx; // index thru traces.

int reset = 0; // 1 => a F1 calls for a reset of F2.

int wini; // the index of the winning node in F2.

int loopCnt; // count of loops thru a resonance.

// main loop.

// for each input trace.

for (traceIndx = 0; traceIndx < rowCnt; traceIndx++)

{

if (DebugFlag >= 1)

cout << "\n\ntrace " << traceIndx << "\n";


// set up a new I.

F1L->setI(inPuts[traceIndx]);


// clear V.

for (i = 0; i < N; i++)

F1L->VReg->Reg[i] = 0;


// init F2.

F2L->init();



cout << "ART1MASPAR::run F2L->nodeNum = " << F2L->nodeNum << endl;


loopCnt = 0; // start guard counter.

try {

// run until resonance or loop bound is reached.

// F1 returns 1 when there is a reset.

// if there's no reset, a resonance has

// occurred.

while(F1L->run() == 1)

{

// there was a reset.

F2L->reset(); // reset.

wini = F2L->run(); // run F2.


// check loop.

if (loopCnt++ > 20)

{

throw Up("***** loopCnt > 20 \n");

}

}

}

catch(const Up& uppity)

{

cout << "*** " << uppity.getUp() << "\n";

terminate();

}

// got a resonance.

cout << "Resonance on unit " << wini << " for pattern " <<

traceIndx << "\n";


// update LTM weights.

try {

F1L->LTMBU->learn(wini, F1L->getS());

F2L->LTMTD->learn(wini, F1L->getS());

}

catch(const Up& uppity)

{

cout << "*** " << uppity.getUp() << "\n";

terminate();

}

} // for all traces.


// dump LTM.

cout << "Zbu " "\n";

F1L->LTMBU->dump();

cout << "Ztd " "\n";

F2L->LTMTD->dump();

}

//

// main()

//

void main(int argc, char** argv)

{

int i,m,n;

ART1MASPAR* Mas;


cout << "ART1 V3.0\n";


if (argc < 2)

{

cout << "Usage: art1 <filename>\n";

return;

}

Mas = new ART1MASPAR(argv[1]);

Mas->run();

}

//

// ART1_Interfac() - use file name, calling interface for a DLL

// packaging.

// Not in use yet.

void ART1MASPAR::ART1_Interfac(char* filenam) {

ART1MASPAR* Mas;

cout << "ART1 .dll V3.0\n";

Mas = new ART1MASPAR(filenam); // put on heap.

}



//

// ART1_Interfac() - use new trace, calling interface for a DLL

// packaging.

// Not in use yet.

//

void ART1MASPAR::ART1_Interfac(int tri, char* filenam) {

ART1MASPAR* Mas;


cout << "ART1 new trace .dll V3.0\n";

Mas = new ART1MASPAR(filenam);

}

--------------------------------

// F1Layer.cpp

// (c) Indra's Net Farm - 2002

// trans(c) Tim McFadden

// This code is released to be used entirely at the user's own risk

// for any consequences what so ever.

// Please keep the Indra's Net Farm name on copied code.

#include <iostream>

#include <math.h>

#include "F1Layer.h"

#include "Up.h"

#include "Dumpster.h"

//

// F1Layer::F1Layer() - constructor.

//

F1Layer::F1Layer (int _n, float _A1, float _B1, float _C1, float _D1,

int _debug) : Layer (_n),

A1(_A1), B1(_B1), C1(_C1), D1(_D1), DebugFlag(_debug)

{

// create registers.

X = new float[nodeNum];

S = new float[nodeNum];

TReg = new FloatReg(nodeNum);

}

//

// F1Layer::run() - run the F1 layer.

// returns:

// 0 => no reset.

// 1 => reset.

// throws Up.

//

int F1Layer::run() throw(Up)

{

int i,j,k;

int reset = 0;

int* hist = new int[HISTNUM];

if (DebugFlag >= 1)

cout << "run F1\n";


// is F2 active?

if (magItF(VReg->Reg, nodeNum) <= 0)

{

// nope - don't look at V.

for (i = 0; i < nodeNum; i++)

{

float Ii;

Ii = (float)IReg->Reg[i];

X[i] = (Ii / (1.0 + A1 * Ii));

}

reset = 1; // by default.

}

else // yup.

{

// use V and I.

// update X[i].

for (i = 0; i < nodeNum; i++)

{

float Ii;

float Vi;

float divisor;


Ii = (float)IReg->Reg[i];

Vi = VReg->Reg[i];



// Xi = (Ii + D1 * Vi - B1) /

// (1 + A1 * (Ii + D1 * Vi) + C1)

if ((divisor = 1.0 + A1 * (Ii + D1 * Vi) + C1) < .0001)

throw (Up("********* F1 run < 0"));


X[i] = (Ii + D1 * Vi - B1) / divisor;

}

reset = 0;

}

if (DebugFlag >= 2)

{

cout << "reset = " << reset << "\n";

cout << "X = \n";

Dumpster().dumpVecF(X, nodeNum);

cout << "XOR I,V = \n";

Dumpster().dumpXOR(IReg->Reg, VReg->Reg, nodeNum);

cout << "V = \n";

Dumpster().dumpVecF(VReg->Reg, nodeNum);

}

// make all Xi >= 0.

// is used for the histogram technique below.

float Xmin = 100.0;

for (i = 0; i < nodeNum; i++)

if (Xmin > X[i])

Xmin = X[i];


if (Xmin <= 0)

for (i = 0; i < nodeNum; i++)

X[i] += -Xmin + HIST_DIF;


// sample S from h(Xi).

// get histogram of X.

for (i = 0; i < HISTNUM; i++)

hist[i] = 0;

for (i = 0; i < nodeNum; i++)

for (j = 1; j < HISTNUM + 1; j++)

if ( (X[i] <= HIST_DIF * j + HIST_MIN) &&

(X[i] > HIST_DIF * (j - 1) + HIST_MIN)

)

hist[j - 1]++;

// use histogram to find max and estimate next peak.

// The histogram peak method is from "Algorithms for Image

// Processing and Computer Vision", J. R. Parker.

// We use (k - j) ^ 4 instead of (k - j) ^ 2.

int histMaxi;

float peakMax2 = -4.0;

float peakWrk;

float peakAmp;


// find 1st peak.

for (j = 0; j < HISTNUM; j++)

if (hist[HISTNUM - 1 - j] > 0)

break;


if (j == HISTNUM)

throw (Up("********* bad histogram"));


j = HISTNUM - 1 - j;


if (DebugFlag >= 2)

{

cout << "X[] max = " << HIST_DIF * j + HIST_MIN << "\n";

}


histMaxi = j;


// find next peak.

// we want to make Xi <= second peak zero.

// for each X[i], see where it fits in histogram.

// compare to a working maximum, but multiply

// by (k - j) ^ 4 to give it a chance to be max.

for (i = 0; i < nodeNum; i++)

{

// find this X[i] in histogram.

for (j = 1; j < HISTNUM + 1; j++)

if ( (X[i] <= HIST_DIF * j + HIST_MIN) &&

(X[i] > HIST_DIF * (j - 1) + HIST_MIN)

)

break;


int histFact = (j - 1) - histMaxi;


peakAmp = histFact * histFact* histFact * histFact;


if (peakAmp * X[i] > peakMax2)

peakMax2 = X[i];

}


if (DebugFlag >= 2)

{

cout << "second peak max = " << peakMax2 << "\n";

}


// map X onto {1, 0} in S using second peak as the threshold.

for (i = 0; i < nodeNum; i++)

if (X[i] > peakMax2 + HIST_DIF)

S[i] = 1.0;

else

S[i] = 0;


if (DebugFlag >= 2)

{

cout << "S = \n";

Dumpster().dumpVecF(S, nodeNum);

}

// check reset.

if (reset == 0)

reset = Ori->doReset(IReg->Reg, S);


// T = S . Zbu.

// this is the output to F2.

TReg->Reg = LTMBU->dot(S);


if (DebugFlag >= 2)

{

cout << "T = S . Zbu =\n";

Dumpster().dumpVecF(TReg->Reg, TReg->length);

}


return reset;

}

//

// F1Layer::getS() - return S[].

//

float* F1Layer::getS()

{

return S;

}

//

// F1Layer::setI() - put the values into I[].

//

void F1Layer::setI(int* _I)

{

for (int i = 0; i < nodeNum; i++)

IReg->Reg[i] = _I[i];

}

--------------------------------

// F2Layer.cpp

// (c) Indra's Net Farm - 2002

// trans(c) Tim McFadden

// This code is released to be used entirely at the user's own risk

// for any consequences what so ever.

// Please keep the Indra's Net Farm name on copied code.

#include <iostream>

#include "F2Layer.h"

#include "Up.h"

#include "Dumpster.h"

//

// F2Layer::F2Layer() - constructor.

//

F2Layer::F2Layer (int _m, int _debug) : Layer(_m), DebugFlag(_debug)

{

// create registers.

U = new float[nodeNum];

Y = new float[nodeNum];


// and droplist.

droplist = new int[nodeNum];


wini = -1; // signal that compete hasn't been run.

}

//

// F2Layer::run () - run the F2 layer.

// returns the index of the winning F2 node.

// side effect - also sets this index in F2Layer.wini.

// throws Up.

//

int

F2Layer::run () throw(Up)

{

int i,j,k;

if (DebugFlag >= 1)

cout << "run F2\n";


// turn off inhibited units.

for (i = 0; i < nodeNum; i++)

TReg->Reg[i] = (droplist[i] == 1? TReg->Reg[i] : 0);

// compete to find a critical feature pattern.

compete();


// sample to U and find the winning node, wini.

wini = -1; // mark not found.


for (i = 0; i < nodeNum; i++)

{

U[i] = TReg->Reg[i] > 0 ? 1 : 0;

if (U[i] == 1)

wini = i;

}


if (wini == -1)

throw (Up("********* wini not found"));



// V = U . Ztd .

// output to F1.

VReg->Reg = LTMTD->dot(U);

return wini;

}


//

// F2Layer::init() - init F2.

//

void

F2Layer::init()

{

int i,j,k;


// init drop list.

for (i = 0; i < nodeNum; i++)

droplist[i] = 1;

}

//

// F2Layer::compete() - find the winning node in F2 = max(T[i]).

//

void F2Layer::compete()

{

int i,j,k;

int maxi = -1;

float max = -1;



// compete to get Y, just the max() of T.

for (i = 0; i < nodeNum; i++)

{

if (max < TReg->Reg[i])

{

max = TReg->Reg[i];

maxi = i;

}

}

if (maxi == -1)

{

cout << "*** compete() maxi = -1, no winner." << endl;

}

if (DebugFlag >= 2)

{

cout << "compete() maxi = " << maxi << endl;

cout << "compete() max = " << max << endl;

}


// clear out every one but the winner.

for (i = 0; i < nodeNum; i++)

{

if (maxi != i)

TReg->Reg[i] = 0;

}


if (DebugFlag >= 2)

{

cout << "compete() T =\n";

Dumpster().dumpVecF(TReg->Reg, TReg->length);

}


}


//

// F2Layer::reset() - set the last used node to 0 in the drop list.

//

void

F2Layer::reset()

{

// if F2 has been run, drop the last used F2 node from the active list.

if (wini >= 0)

droplist[wini] = 0;

}

--------------------------------


// Layer.cpp

// (c) Indra's Net Farm - 2002

// trans(c) Tim McFadden

// This code is released to be used entirely at the user's own risk

// for any consequences what so ever.

// Please keep the Indra's Net Farm name on copied code.


#include "Layer.h"

//

// Layer::magIt() - int magnitude.

//

int

Layer::magIt(int* _I, int _n)

{

int mag = 0;


for (int i = 0; i < _n; i++)

mag += _I[i];


return mag;

}


//

// Layer::magItF() - float magnitude.

//

float

Layer::magItF(float* _I, int _n)

{

float mag = 0;


for (int i = 0; i < _n; i++)

{

if (_I[i] < 0)

mag += -_I[i];

else

mag += _I[i];


}


return mag;

}

--------------------------------


// LayerFactory.cpp

// (c) Indra's Net Farm - 2002

// trans(c) Tim McFadden

// This code is released to be used entirely at the user's own risk

// for any consequences what so ever.

// Please keep the Indra's Net Farm name on copied code.

#include "LayerFactory.h"

#include "F1Layer.h"

#include "F2Layer.h"



//

// LayerFactory::Make1() -

//

F1Layer*

LayerFactory::Make1(int _m, float _A1, float _B1, float _C1,

float _D1, int _debug)

{

return new F1Layer(_m, _A1, _B1, _C1, _D1, _debug);

}


//

// LayerFactory::Make2()

//

F2Layer*

LayerFactory::Make2(int _m, int _debug)

{

return new F2Layer(_m, _debug);

}

--------------------------------


// LTMBottomUp.cpp

// (c) Indra's Net Farm - 2002

// trans(c) Tim McFadden

// This code is released to be used entirely at the user's own risk

// for any consequences what so ever.

// Please keep the Indra's Net Farm name on copied code.

#include <iostream>

#include "LTMBottomUp.h"

#include "Layer.h"

#include "Dumpster.h"

//

// LTMBottomUp::LTMBottomUp () - constructor.

//

LTMBottomUp::LTMBottomUp (int _n, int _m, float _L, float _BotupFact,

int _debug) : LTM(_n, _m)

{

int i,j,k;


Z = new float[maxN][maxM];

L = _L;

DebugFlag = _debug;

BotupFact = _BotupFact;


// initialize Zbu(0).

for (i = 0; i < n; i++)

{

for (j = 0; j < m; j++)

Z[i][j] = L / (L - 1 + m);

}

}

//

// LTMBottomUp::dot() - dot vector into bottom up LTM.

float*

LTMBottomUp::dot(float* x)

{

int i,j,k;


float* ret = new float[maxM];


// dot over i.

for (j = 0; j < m; j++)

{

ret[j] = 0;

for (i = 0; i < n; i++)

{

ret[j] += x[i] * Z[i][j];

}

}


if (DebugFlag >= 1)

{

cout << "x . LTMBU\n";

Dumpster().dumpVecF(ret, m);

}


return ret;

}

//

// LTMBottomUp::learn() - run fast learning rule.

void

LTMBottomUp::learn(int _wini, float* _S) throw(Up)

{

int i,j,k;

float mag = 0;



mag = Layer().magItF(_S, n);

// change from Carpenter and Grossberg.

// In the case of input patterns that have successively more

// ones set, the values in T of uncommitted F2 nodes in

// LTM may have larger values than the committed - hence

// the committed nodes will not be tried. To overcome this,

// the values for non-zero S are multiplied by a factor

// BotupFact > 1. This makes the committed nodes larger

// in LTM.

for (i = 0; i < n; i++)

if (_S[i] >= 1)

Z[i][_wini] = BotupFact * L / (L - 1 + mag);

else

Z[i][_wini] = 0;

}

//

// LTMBottomUp::dump() - dump BU LTM.

//

void LTMBottomUp::dump()

{

float *momo;


momo = *Z;


Dumpster().dumpMatrix(momo, n, m);

}

--------------------------------


// LTMTopDown.cpp

// (c) Indra's Net Farm - 2002

// trans(c) Tim McFadden

// This code is released to be used entirely at the user's own risk

// for any consequences what so ever.

// Please keep the Indra's Net Farm name on copied code.

#include "LTMTopDown.h"

#include "Dumpster.h"

//

// LTMTopDown::LTMTopDown () - constructor

LTMTopDown::LTMTopDown (int _n, int _m, float _b1, float _d1,

int _debug) : LTM(_n, _m), B1(_b1), D1(_d1), DebugFlag(_debug)

{

int i, j, k;


// allocate top down LTM.

Z = new float[maxM][maxN];


// initialize Ztd(0).

for (i = 0; i < m; i++)

{

for (j = 0; j < n; j++)

Z[i][j] = (B1 - 1) / D1;

}

}

///

// LTMTopDown::dot() - dot vector into top down LTM.

float*

LTMTopDown::dot(float* x)

{

int i,j,k;


float* ret = new float[maxN];


// dot over i.

for (j = 0; j < n; j++)

{

ret[j] = 0;

for (i = 0; i < m; i++)

ret[j] += x[i] * Z[i][j];

}



return ret;

}

//

// LTMTopDown::learn() - use fast learning.

void

LTMTopDown::learn(int _wini, float* _S) throw(Up)

{

int i,j,k;


for (i = 0; i < n; i++)

Z[_wini][i] = _S[i];

}

//

// LTMTopDown::dump() - dump the TD LTM.

//

void

LTMTopDown::dump()

{

float *momo;


momo = *Z;

if (DebugFlag >= 1)

Dumpster().dumpMatrix(momo, m, n);


cout << "critical feature patterns\n";

for (int i = 0; i < m; i++)

{

cout << "patt " << i << "\n";

for (int j = 0; j < 25; j++)

{

if ((j > 0) && (j % 5) == 0)

cout << "\n";

cout << Z[i][j] << " ";

}

cout << "\n";

}

}

--------------------------------


// Orienting.cpp

// Orienting.h

// (c) Indra's Net Farm - 2002

// trans(c) Tim McFadden

// This code is released to be used entirely at the user's own risk

// for any consequences what so ever.

// Please keep the Indra's Net Farm name on copied code.


#include "Orienting.h"

//

// Orienting::Orienting() - constructor.

//

Orienting::Orienting(float _rho, int _N) : Layer(_N)

{

rho = _rho;

nodeNum = _N;

}

//

// Orienting::doReset( -

// returns:

// 0 => no reset.

// 1 => reset.

//

int Orienting::doReset(int* _I, float* _X)

{

// reset when rho > |X| / |I|.

if (rho > (magItF(_X, nodeNum) / magIt(_I, nodeNum)))

return 1;

else

return 0;

}

--------------------------------


// TraceParse.cpp

// (c) Indra's Net Farm - 2002

// trans(c) Tim McFadden

// This code is released to be used entirely at the user's own risk

// for any consequences what so ever.

// Please keep the Indra's Net Farm name on copied code.

// Changes

// 10/20/04 - use file input.


#include <iostream>

#include <fstream>

#include <string.h>

#include "ART1MASPAR.h"

#include "TraceParse.h"

#include "Up.h"

// structure to hold operands.

struct nameVal

{

char name[20];

int intNum;

} ;

// map name to code.

struct nameVal namez[] = { {"M", TraceParse::NAME_M},

{"N", TraceParse::NAME_N},

{"A1", TraceParse::NAME_A1},

{"B1", TraceParse::NAME_B1},

{"C1", TraceParse::NAME_C1},

{"Epsilon", TraceParse::NAME_EPSILON},

{"A2", TraceParse::NAME_A2},

{"B2", TraceParse::NAME_B2},

{"C2", TraceParse::NAME_C2},

{"Rho", TraceParse::NAME_RHO},

{"L", TraceParse::NAME_L},

{"D1", TraceParse::NAME_D1},

{"Debug", TraceParse::NAME_DEBUG},

{"BotupFact", TraceParse::NAME_BUPF},

};

//

// TraceParse::parse() - parse an input set of a header and a set of traces.

// TraceParse is a friend of ART1MASPAR and the input values are placed there.

//

void

TraceParse::parse(ART1MASPAR* z, char* fnam)

{

char wrkStr[300];


MASp = z;

rowCnt = 0;


// open up.

Ins.open(fnam);


if (!Ins)

{

cout << "TraceParse bad open " << fnam << endl;

terminate();

}


// start with header.

Ins >> wrkStr;

if (wrkStr[0] == '(')

{

Ins >> wrkStr; // header.

if (strncmp(wrkStr, "header", 6) == 0)

{

try

{

header();

}

catch(const Up& uppity)

{

cout << "TraceParse " << uppity.getUp() << "\n";

terminate();

}

}


Ins >> wrkStr; // trace.

cout << wrkStr << "\n";


// there may now follow a number of input traces.

while (strncmp(wrkStr, "trace", 5) == 0)

{

trace();

rowCnt++;


if (Ins.eof())

break;


Ins >> wrkStr; // trace?.

cout << wrkStr << "\n";

}

}


MASp->rowCnt = rowCnt;

}

//

// TraceParse::header() - parse the header.

// throws Up.

//

void

TraceParse::header() throw(Up)

{

char wrkStr[300];

int wrkInt;

float wrkFloat;

keyNames keyId;

int i,j,k;

Ins >> wrkStr;

if (wrkStr[0] == '(')

{

while (!Ins.eof())

{

Ins >> wrkStr; // operand.

if(wrkStr[0] == ')')

break;


cout << wrkStr << " = ";


// try for a keyword.

keyId = TraceParse::NAME_NOT_HERE;

for (i = 0; i < sizeof(namez) / sizeof(struct nameVal); i++)

{

if (strcmp(wrkStr, namez[i].name) == 0)

keyId = keyNames(namez[i].intNum);

}

if (keyId == TraceParse::NAME_NOT_HERE)

throw Up("*** header operand not found\n", wrkStr);


// parse each keyword value.

switch(keyId)

{

case NAME_M :

lexChar(PARSE_LOOK_DIGIT);

Ins >> wrkInt;

cout << wrkInt << "\n";

MASp->M = wrkInt;

break;


case NAME_N :

lexChar(PARSE_LOOK_DIGIT);

Ins >> wrkInt;

cout << wrkInt << "\n";

MASp->N = wrkInt;

break;


case NAME_A1 :

lexChar(PARSE_LOOK_FLOAT);

Ins >> wrkFloat;

cout << wrkFloat << "\n";

MASp->A1= wrkFloat;

break;


case NAME_B1 :

lexChar(PARSE_LOOK_FLOAT);

Ins >> wrkFloat;

cout << wrkFloat << "\n";

MASp->B1= wrkFloat;

break;


case NAME_C1 :

lexChar(PARSE_LOOK_FLOAT);

Ins >> wrkFloat;

cout << wrkFloat << "\n";

MASp->C1= wrkFloat;

break;


case NAME_D1 :

lexChar(PARSE_LOOK_FLOAT);

Ins >> wrkFloat;

cout << wrkFloat << "\n";

MASp->D1= wrkFloat;

break;


case NAME_D2 :

lexChar(PARSE_LOOK_FLOAT);

Ins >> wrkFloat;

cout << wrkFloat << "\n";

MASp->D2= wrkFloat;

break;

case NAME_L :

lexChar(PARSE_LOOK_FLOAT);

Ins >> wrkFloat;

cout << wrkFloat << "\n";

MASp->L= wrkFloat;

break;


case NAME_EPSILON :

lexChar(PARSE_LOOK_FLOAT);

Ins >> wrkFloat;

cout << wrkFloat << "\n";

MASp->Epsilon = wrkFloat;

break;

case NAME_RHO :

lexChar(PARSE_LOOK_FLOAT);

Ins >> wrkFloat;

cout << wrkFloat << "\n";

MASp->rho = wrkFloat;

break;

case NAME_BUPF :

lexChar(PARSE_LOOK_FLOAT);

Ins >> wrkFloat;

cout << wrkFloat << "\n";

MASp->BotupFact = wrkFloat;

break;

case NAME_DEBUG :

lexChar(PARSE_LOOK_DIGIT);

Ins >> wrkInt;

cout << wrkInt << "\n";

MASp->DebugFlag = wrkInt;

break;

} // switch.


if (Ins.bad())

throw Up("*** header bad input\n");

} // while.



} // if '('

}

//

// TraceParse::trace() - parse a trace.

//

void

TraceParse::trace()

{

char wrkStr[300];

int wrkInt;

int i,j,k;



Ins >> wrkStr;

cout << wrkStr << " ";


if (wrkStr[0] == '(')

{

// read in a trace.

// this is a list of int's

for (i = 0; i < MASp->N; i++)

{

Ins >> wrkInt;

cout << wrkInt << " ";

MASp->inPuts[rowCnt][i] = wrkInt;

}


if (Ins.eof())

return;


Ins >> wrkStr; // dump ')'

cout << wrkStr << ")\n";

cout << "rowCnt = " << rowCnt << "\n";

}

}


//

// TraceParse::lexChar() - check for the correct lexical type.

// throws Up if not happy with type.

//

void

TraceParse::lexChar(unsigned int flags) throw (Up)

{

unsigned int init;

char charz = ' ';


while (!Ins.eof())

{

charz = init = Ins.peek();

if (isspace(charz) )

Ins.get();

else

break;

}


if ((flags & PARSE_LOOK_LETTER) != 0)

{

if (isalpha(charz) == 0)

throw Up("*** expecting name \n");

}

else

if ((flags & PARSE_LOOK_PAREN) != 0)

{

if ( (init!= '(') && (init!= '(') )

throw Up("*** expecting parentheses \n");

}

else

if ((flags & PARSE_LOOK_DIGIT) != 0)

{

if (isdigit(charz) == 0)

throw Up("*** expecting digit \n");

}

else

if ((flags & PARSE_LOOK_FLOAT) != 0)

{

if (init == (int)'.')

return;


if (isdigit(charz) == 0)

throw Up("*** expecting float \n");

}

}