Prime implementation of the HP48/50 MES solver (ish) - Paulo MO - 2026-07-29 03:26, edited 2026-07-29 03:54
Hello
1. I have always considered the MES solver of the HP48/50 series a superbly useful tool. For those who never used it, it works like this:
a. It accepts a list of equations as input. The number of equations may be greater or smaller than the number of variables, as long as they are consistent.
b. It lets the user input values for the known variables;
c. It will then attempt to solve for all the remaining variables in the following way: it scans the set of equations until it finds one equation with a single unknown; it solves that equation for the unknown variable. Then, having one more known variable, it scans again for another equation with a single unknown; it solves it. And so on, until all variables have been found, or no equation with a single unknown remains.
It is therefore not a simultaneous equation solver, but instead a sequential multiple equation solver. Due to that, it does not need a system with exactly as many equations as unknowns. It is the perfect tool to be fed with all the equations pertaining to a given topic (let's say "Butterworth digital filter design") and, afterward, with whatever variables are known, to determine all the remaining variables. The only care is to have enough (possibly redundant) formulas in the formula list, so that the solver will easily find formulas with a single unknown during the solving process.
2. Having recently bought a Prime, I wanted to have this type of solver on it. Helas, no such app or program was to be found. Therefore, I made one. The implementation is clumsy, both in the UI and in some aspects of the code. The Prime and its considerably more "different from expected" programming environment, language, and quirks are new to me, and there seems to be a lack of reference documentation (or I was inefficient in finding it). I was therefore content to have it working at all within the time I had allotted to the project. The code is below, in case anyone is interested. Even though many improvements are possible and, as I said, it is a somewhat clumsy implementation, it does the job well enough to scratch my itch. It may still have bugs, and is being released as is, but maybe it can be useful to someone else.
3. Notes on operation:
a. We can create and modify different sets of equations. Each set can have as many equations as needed, for a maximum total number of 21 variables per set.
b. After selecting a particular set, we can solve it by inputting the known variables. The program will then try to determine all the remaining variables using the equations in the set, using the above-described HP48/50 MES approach;
c. The variables are initially shown with a default value of -999999999, which is meant to convey the message "unknown"; (clumsy, as I said, but the final compromise of my conditional surrender to the Prime INPUT function)
d. After solving the set, the values of the user input variables can be altered, and a new solution can be directly found from the variable input screen. All the automatically determined variables will be recomputed. However, if the set of known variables changes, one needs to exit from the variable input screen, and start a new solve session, thus inputting all known variables again.
e. The program is bilingual (English as default);
f. It can operate in either "verbose" or "quiet" mode. In verbose mode, it will show which particular equation is being solved for each one of the variables to be determined. The default is "quiet" mode, in which only the final values of the variables are shown;
g. Often, viewing the equations included in a set cannot be done adequately, due to the size limitations of the msgbox() function. Therefore, whenever a set is viewed, that particular set of equations is also written to the terminal (accessible by simultaneously pressing ON and / (division operator)), where the viewing conditions are much better.
h. After creating your equation sets, you may want to save the contents of the EQSETS variable in one of the global system list variables (say L0) so that you will not lose them after a recompilation or system reset. If you then lose your sets for some reason, just copy L0 to EQSETS back again, and set EQINIT to 1. The program will then run with the previously saved equation sets.
Enjoy. All one has to do is copy the code into a new program (MES), and then run it (e.g., calling MES from the command line). Even though I am not planning to spend any more time on it, any bug reports/improvement suggestions will be welcome.
Paulo
Code: //=====================================================================
// MES - Sequential Equation Set Manager and Solver HP48/50 style(ish) - Version 0.9
//=====================================================================
// Data model:
// EQSETS is a list of "sets". Each set is a 2-element list:
// { SetName(string), Equations(list of strings) }
// EQSETS itself persists on the calculator as a global variable, but will be
// reset if the program is recompiled. Therefore, it may be useful to save
// its contents in a more permanent location (L0, for example).
//
//=====================================================================
EXPORT EQSETS;
EXPORT EQINIT;
EXPORT CVARS; // variable names for the equation set currently being solved
EXPORT CVALS; // parallel list of values (defaultVal() means "not yet known")
EXPORT CSTAT; // parallel list of status codes: 0=unknown,1=user-entered,2=solved
//---------------------------------------------------------------
//Default position of the toggle settings
//---------------------------------------------------------------
verbose:=0;
language:="english";
//---------------------------------------------------------------
// Ensure EQSETS exists exactly once (first run after install/reset)
//---------------------------------------------------------------
initStorage()
BEGIN
IF EQINIT<>1 THEN
EQSETS:={};
EQINIT:=1;
END;
END;
//---------------------------------------------------------------
// To circumvent the absence of chained indexing EQSETS(idx)(1)/(2)
//---------------------------------------------------------------
setName(idx)
BEGIN
LOCAL t;
t:=EQSETS(idx);
RETURN t(1);
END;
setEqs(idx)
BEGIN
LOCAL t;
t:=EQSETS(idx);
RETURN t(2);
END;
//---------------------------------------------------------------
// Remove element idx from list L, and return the new list
//---------------------------------------------------------------
listRemove(L,idx)
BEGIN
LOCAL i,n,R;
R:={};
n:=SIZE(L);
FOR i FROM 1 TO n DO
IF i<>idx THEN
R(SIZE(R)+1):=L(i);
END;
END;
RETURN R;
END;
//---------------------------------------------------------------
// Get the list of set names (for CHOOSE dialogs)
//---------------------------------------------------------------
getSetNames()
BEGIN
LOCAL i,n,names;
names:={};
n:=SIZE(EQSETS);
FOR i FROM 1 TO n DO
names(SIZE(names)+1):=setName(i);
END;
RETURN names;
END;
//---------------------------------------------------------------
// Add one equation to set idx, prompting via INPUT
//---------------------------------------------------------------
addEquation(idx)
BEGIN
LOCAL eq,eqs;
eq:="";
IF language=="english" THEN
IF INPUT({{eq,[2]}},"Add Equation","Equation:","e.g. A+B=C",0,"")==0 THEN RETURN; END;
ELSE
IF INPUT({{eq,[2]}},"Adicionar Equação","Equação:","e.g. A+B=C",0,"")==0 THEN RETURN; END;
END;
IF eq=="" THEN RETURN; END;
eqs:=setEqs(idx);
eqs(SIZE(eqs)+1):=eq;
EQSETS(idx):={setName(idx),eqs};
END;
//---------------------------------------------------------------
// After creating a set, loop asking to add equations
//---------------------------------------------------------------
editEquationsLoop(idx)
BEGIN
LOCAL more;
more:=1;
WHILE more==1 DO
addEquation(idx);
more:=0;
IF language=="english" THEN
CHOOSE(more,"Add Another Equation?","Yes","No");
ELSE
CHOOSE(more,"Adicionar outra Equação?","Sim","Não");
END;
END;
END;
//---------------------------------------------------------------
// New Set
//---------------------------------------------------------------
newSet()
BEGIN
LOCAL nm,i,n;
nm:="";
IF language=="english" THEN
IF INPUT({{nm,[2]}},"New Set","Name:","Enter a name for this equation set","","")==0 THEN RETURN; END;
ELSE
IF INPUT({{nm,[2]}},"Novo Set","Nome:","Qual o nome do novo set?","","")==0 THEN RETURN; END;
END;
IF nm=="" THEN RETURN; END;
IF SIZE(EQSETS)<>0 THEN
n:=SIZE(EQSETS);
FOR i FROM 1 TO n DO
IF setName(i)==nm THEN
IF language=="english" THEN
MSGBOX("A set with that name already exists.");
ELSE
MSGBOX("Já existe um set com esse nome.");
END;
RETURN;
END;
END;
END;
EQSETS(SIZE(EQSETS)+1):={nm,{}};
editEquationsLoop(SIZE(EQSETS));
END;
//---------------------------------------------------------------
// Delete Set
//---------------------------------------------------------------
deleteSet()
BEGIN
LOCAL names,sel,conf;
IF SIZE(EQSETS)==0 THEN
IF language=="english" THEN
MSGBOX("No equation sets exist.");
ELSE
MSGBOX("Não há sets de equações.");
END;
RETURN;
END;
names:=getSetNames();
sel:=0;
IF language=="english" THEN
CHOOSE(sel,"Delete Which Set?",names);
ELSE
CHOOSE(sel,"Qual o set a apagar?",names);
END;
IF sel==0 THEN RETURN; END;
conf:=0;
IF language=="english" THEN
CHOOSE(conf,"Confirm Delete","Yes, delete \""+setName(sel)+"\"","No, cancel");
ELSE
CHOOSE(conf,"Confirme","Sim, apaga \""+setName(sel)+"\"","Não, cancela");
END;
IF conf==1 THEN
EQSETS:=listRemove(EQSETS,sel);
IF language=="english" THEN
MSGBOX("Set deleted.");
ELSE
MSGBOX("Set apagado.");
END;
END;
END;
//---------------------------------------------------------------
// View equations in a set
//---------------------------------------------------------------
viewEquations(idx)
BEGIN
LOCAL eqs,i,s;
eqs:=setEqs(idx);
IF SIZE(eqs)==0 THEN
IF language=="english" THEN
MSGBOX("This set has no equations yet.");
ELSE
MSGBOX("Este set ainda não tem equações.");
END;
RETURN;
END;
s:="";
FOR i FROM 1 TO SIZE(eqs) DO
s:=s+STRING(i)+": "+eqs(i)+CHAR(10);
END;
PRINT("****** Set "+setName(idx)+" *********");
PRINT(s);
MSGBOX(s);
END;
//---------------------------------------------------------------
// Edit one equation
//---------------------------------------------------------------
editEquation(idx)
BEGIN
LOCAL eqs,sel,neweq;
eqs:=setEqs(idx);
IF SIZE(eqs)==0 THEN
IF language=="english" THEN
MSGBOX("No equations to edit.");
ELSE
MSGBOX("Não há equações para editar.");
END;
RETURN;
END;
sel:=0;
IF language=="english" THEN
CHOOSE(sel,"Edit Which Equation?",eqs);
ELSE
CHOOSE(sel,"Qual a equação a editar?",eqs);
END;
IF sel==0 THEN RETURN; END;
neweq:=eqs(sel);
IF language=="english" THEN
IF INPUT({{neweq,[2]}},"Edit Equation","Equation:","Modify and press OK",0,eqs(sel))==0 THEN RETURN; END;
ELSE
IF INPUT({{neweq,[2]}},"Editar Equação","Equação:","Modifique e pressione OK",0,eqs(sel))==0 THEN RETURN; END;
END;
IF neweq=="" THEN RETURN; END;
eqs(sel):=neweq;
EQSETS(idx):={setName(idx),eqs};
END;
//---------------------------------------------------------------
// Delete one equation
//---------------------------------------------------------------
deleteEquation(idx)
BEGIN
LOCAL eqs,sel,conf;
eqs:=setEqs(idx);
IF SIZE(eqs)==0 THEN
IF language=="english" THEN
MSGBOX("No equations to delete.");
ELSE
MSGBOX("Não há equações para apagar.");
END;
RETURN;
END;
sel:=0;
IF language=="english" THEN
CHOOSE(sel,"Delete Which Equation?",eqs);
ELSE
CHOOSE(sel,"Qual a equação a apagar?",eqs);
END;
IF sel==0 THEN RETURN; END;
conf:=0;
IF language=="english" THEN
CHOOSE(conf,"Confirm Delete","Yes, delete","No, cancel");
ELSE
CHOOSE(conf,"Confirme","Sim, apaga","Não, cancela");
END;
IF conf==1 THEN
eqs:=listRemove(eqs,sel);
EQSETS(idx):={setName(idx),eqs};
IF language=="english" THEN
MSGBOX("Equation deleted.");
ELSE
MSGBOX("Equação apagada.");
END;
END;
END;
//---------------------------------------------------------------
// Rename a set
//---------------------------------------------------------------
renameSet(idx)
BEGIN
LOCAL nm,i,n,cur;
cur:=setName(idx);
nm:=cur;
IF INPUT({{nm,[2]}},"Rename Set","New name:","Enter new name",0,cur)==0 THEN RETURN; END;
IF nm=="" THEN RETURN; END;
n:=SIZE(EQSETS);
FOR i FROM 1 TO n DO
IF i<>idx AND setName(i)==nm THEN
IF language=="english" THEN
MSGBOX("A set with that name already exists.");
ELSE
MSGBOX("Já existe um set com este nome.");
END;
RETURN;
END;
END;
EQSETS(idx):={nm,setEqs(idx)};
END;
//---------------------------------------------------------------
// Submenu for a given set
//---------------------------------------------------------------
setSubMenu(idx)
BEGIN
LOCAL choice,title;
choice:=0;
REPEAT
title:="Set: "+setName(idx);
IF language=="english" THEN
CHOOSE(choice,title,
"View Equations","Add Equation","Edit Equation",
"Delete Equation","Rename Set","Back");
ELSE
CHOOSE(choice,title,
"Ver Equações","Adicionar Equação","Editar Equação",
"Apagar Equação","Renomear Set","Back");
END;
IF choice==1 THEN viewEquations(idx); END;
IF choice==2 THEN addEquation(idx); END;
IF choice==3 THEN editEquation(idx); END;
IF choice==4 THEN deleteEquation(idx); END;
IF choice==5 THEN renameSet(idx); END;
UNTIL choice==6 OR choice==0;
END;
//---------------------------------------------------------------
// Choose a set, then open its submenu
//---------------------------------------------------------------
editSetMenu()
BEGIN
LOCAL names,sel;
IF SIZE(EQSETS)==0 THEN
IF language=="english" THEN
MSGBOX("No equation sets exist. Create one first.");
ELSE
MSGBOX("Não há sets de equações. Crie um primeiro.");
END;
RETURN;
END;
names:=getSetNames();
sel:=0;
IF language=="english" THEN
CHOOSE(sel,"Edit Which Set?",names);
ELSE
CHOOSE(sel,"Qual o set a editar?",names);
END;
IF sel==0 THEN RETURN; END;
setSubMenu(sel);
END;
//=====================================================================
// SOLVE SECTION - (FINNALY)
//=====================================================================
// Default value meaning "this variable's value is not yet known".
// Do not use this exact number as a genuine variable value.
defaultVal()
BEGIN
RETURN -999999999;
END;
//---------------------------------------------------------------
// Parsing utilities
//---------------------------------------------------------------
isLetter(c)
BEGIN
IF (CHAR(c) >= "A" AND CHAR(c) <= "Z") OR (CHAR(c) >= "a" AND CHAR(c) <= "z") THEN
RETURN 1;
ELSE
RETURN 0;
END;
END;
isDigit(c)
BEGIN
IF CHAR(c) >= "0" AND CHAR(c) <= "9" THEN
RETURN 1;
ELSE
RETURN 0;
END;
END;
isAlnum(c)
BEGIN
IF (isLetter(c) OR isDigit(c)) THEN
RETURN 1;
ELSE
RETURN 0;
END;
END;
isInList(x,L)
BEGIN
LOCAL i,n;
n:=SIZE(L);
FOR i FROM 1 TO n DO
IF L(i)==x THEN RETURN 1; END;
END;
RETURN 0;
END;
//---------------------------------------------------------------
// Extract unique variable-names from one equation
// (A variable name is a run of letters/digits starting with a letter. If it is
// immediately followed by a "(", it is treated as a function name (e.g. SIN)
// and is not counted as a variable name.
//---------------------------------------------------------------
extractVarsFromEq(eqstr)
BEGIN
LOCAL n,i,c,tok,vars,isFunc,j;
n:=SIZE(eqstr);
vars:={};
i:=1;
WHILE i<=n DO
c:=eqstr(i);
IF isLetter(c) THEN
tok:=CHAR(c);
j:=i+1;
WHILE j<=n AND isAlnum(eqstr(j)) DO
tok:=tok+CHAR(eqstr(j));
j:=j+1;
END;
isFunc:=0;
IF j<=n THEN
IF CHAR(eqstr(j))=="(" THEN isFunc:=1; END;
END;
IF isFunc==0 THEN
IF isInList(tok,vars)==0 THEN
vars(SIZE(vars)+1):=tok;
END;
END;
i:=j;
ELSE
i:=i+1;
END;
END;
RETURN vars;
END;
//---------------------------------------------------------------
// Union of all variables across every equation in a set
//---------------------------------------------------------------
getSetVariables(idx)
BEGIN
LOCAL eqs,i,n,v,allVars,j,m;
eqs:=setEqs(idx);
allVars:={};
n:=SIZE(eqs);
FOR i FROM 1 TO n DO
v:=extractVarsFromEq(eqs(i));
m:=SIZE(v);
FOR j FROM 1 TO m DO
IF isInList(v(j),allVars)==0 THEN
allVars(SIZE(allVars)+1):=v(j);
END;
END;
END;
RETURN allVars;
END;
//---------------------------------------------------------------
// Replace every KNOWN variable name in eqstr with its value
// Uses the global CVARS/CVALS. Function-names (followed by "(")
// and still-unknown variable names are left untouched.
//---------------------------------------------------------------
substituteKnowns(eqstr)
BEGIN
LOCAL n,i,c,tok,j,isFunc,outS,pp;
LOCAL kk,foundIdx;
n:=SIZE(eqstr);
outS:="";
i:=1;
WHILE i<=n DO
c:=eqstr(i);
IF isLetter(c) THEN
tok:=CHAR(c);
j:=i+1;
WHILE j<=n AND isAlnum(eqstr(j)) DO
tok:=tok+CHAR(eqstr(j));
j:=j+1;
END;
isFunc:=0;
IF j<=n THEN
IF CHAR(eqstr(j))=="(" THEN isFunc:=1; END;
END;
IF isFunc==1 THEN
outS:=outS+tok;
ELSE
//This tok is a variable name. Let us see if it is known
foundIdx:=0;
kk:=MIN(SIZE(CVARS),21);
//For each variable in the set
FOR pp FROM 1 TO kk DO
//If the name checks and it is still unknown, them flag having found an unknown
IF CVARS(pp)==tok AND CVALS(pp)<>defaultVal() THEN
foundIdx:=pp;
END;
END;
//fill in the value of the unknown variable or keep the variable name
IF foundIdx>0 THEN
outS:=outS+STRING(CVALS(foundIdx));
ELSE
outS:=outS+tok;
END;
END;
i:=j;
ELSE
outS:=outS+CHAR(c);
i:=i+1;
END;
END;
RETURN outS;
END;
//---------------------------------------------------------------
// Solve one equation (with values of known variables already substituted) for one variable
// Returns {1,value} on success, {0,0} on failure.
//---------------------------------------------------------------
solveOneVar(eqstr,varname)
BEGIN
LOCAL sol;
IF verbose==1 THEN
IF language=="english" THEN
MSGBOX("Solving "+CHAR(10)+eqstr+CHAR(10)+"for "+varname);
ELSE
MSGBOX("A resolver "+CHAR(10)+eqstr+CHAR(10)+"para obter "+varname);
END;
END;
IFERR
sol:=fsolve(EVAL(eqstr),EVAL(varname),10);
THEN
RETURN {0,0};
END;
IF SIZE(sol)==0 THEN
RETURN {0,0};
ELSE
RETURN {1,sol};
END;
END;
//---------------------------------------------------------------
// Find candidate equations for solving (criterion: does it have exactly one unknown?)
// Returns {1,varIndex,value} if solved, {0,0,0} otherwise.
//---------------------------------------------------------------
tryEquation(eqstr)
BEGIN
LOCAL vlist,m,i,idx2,unknownCount,unknownIdx,subEq;
LOCAL sol,pp;
vlist:=extractVarsFromEq(eqstr);
m:=SIZE(vlist);
unknownCount:=0;
unknownIdx:=0;
FOR i FROM 1 TO m DO
idx2:=0;
FOR pp FROM 1 TO MIN(SIZE(CVARS),21) DO
IF CVARS(pp)==vlist(i) THEN idx2:=pp; END;
END;
IF idx2>0 THEN
IF CVALS(idx2)==defaultVal() THEN
unknownCount:=unknownCount+1;
unknownIdx:=idx2;
END;
END;
END;
IF unknownCount<>1 THEN
RETURN {0,0,0};
END;
IF verbose==1 THEN
IF language=="english" THEN
MSGBOX("Going to solve equation "+CHAR(10)+eqstr+CHAR(10)+"for "+CVARS(unknownIdx));
ELSE
MSGBOX("Vou usar a equação "+CHAR(10)+eqstr+CHAR(10)+"para obter "+CVARS(unknownIdx));
END;
END;
subEq:=substituteKnowns(eqstr);
sol:=solveOneVar(subEq,CVARS(unknownIdx));
IF sol(1)==0 THEN
RETURN {0,0,0};
END;
IF verbose==1 THEN
MSGBOX(CVARS(unknownIdx)+" = "+sol(2));
END;
RETURN {1,unknownIdx,sol(2)};
END;
//---------------------------------------------------------------
// Iterate the scan of the set's equations until no further progress is made
//---------------------------------------------------------------
solveIterate(idx)
BEGIN
LOCAL eqs,n,progress,ei,res;
eqs:=setEqs(idx);
n:=SIZE(eqs);
progress:=1;
WHILE progress==1 DO
progress:=0;
FOR ei FROM 1 TO n DO
res:=tryEquation(eqs(ei));
IF res(1)==1 THEN
CVALS(res(2)):=res(3);
CSTAT(res(2)):=2;
progress:=1;
END;
END;
END;
END;
//---------------------------------------------------------------
// The solve input/results screen
// Returns 1 to keep showing the screen again, 0 when the user cancels out.
//---------------------------------------------------------------
solveScreen(idx)
BEGIN
LOCAL labels,help,rsvd,ok,n,pp,prevals;
LOCAL var1, var2, var3, var4, var5, var6, var7;
LOCAL var8, var9, var10, var11, var12, var13, var14;
LOCAL var15, var16, var17, var18, var19, var20, var21;
n:=SIZE(CVARS);
// Warn the user that there is an (arbitrary) limit of 21 variables per set (two input pages)
IF n>21 THEN
IF language=="english" THEN
MSGBOX("Each equation set can have only up to 21 variables.");
ELSE
MSGBOX("Cada set de equações só pode ter até 21 variáveis.");
END;
n:=21;
END;
labels:=MAKELIST("",pp,1,21,1);
IF language=="english" THEN
help:=MAKELIST("Enter a numeric value",pp,1,21,1);
ELSE
help:=MAKELIST("Entre um valor numérico",pp,1,21,1);
END;
rsvd:=MAKELIST(0,pp,1,21,1);
FOR pp FROM 1 TO 21 DO
IF pp<=n then
IF CSTAT(pp)==1 THEN
labels(pp):=CVARS(pp)+" [User]:";
END;
IF CSTAT(pp)==2 THEN
labels(pp):=CVARS(pp)+" [Auto]:";
END;
IF CSTAT(pp)==0 THEN
labels(pp):=CVARS(pp)+" [?]:";
END;
ELSE
labels(pp):="var"+pp+":";
END;
END;
prevals:=CVALS;
ok:=INPUT({var1, var2, var3, var4, var5, var6, var7, var8,
var9, var10, var11, var12, var13, var14, var15, var16,
var17, var18, var19, var20, var21}, "Solve: "+setName(idx),labels, help,rsvd, prevals);
IF ok==0 THEN
RETURN 0;
END;
// For every new computation, force any previously automatically calculated
// variables to their default value, so that they will be recomputed
// with the current values of the user defined variables
IF n>=1 THEN
IF CSTAT(1)==2 THEN
CVALS(1):= defaultVal();
ELSE
CVALS(1):= var1;
END;
END;
IF n>=2 THEN
IF CSTAT(2)==2 THEN
CVALS(2):= defaultVal();
ELSE
CVALS(2):= var2;
END;
END;
IF n>=3 THEN
IF CSTAT(3)==2 THEN
CVALS(3):= defaultVal();
ELSE
CVALS(3):= var3;
END;
END;
IF n>=4 THEN
IF CSTAT(4)==2 THEN
CVALS(4):= defaultVal();
ELSE
CVALS(4):= var4;
END;
END;
IF n>=5 THEN
IF CSTAT(5)==2 THEN
CVALS(5):= defaultVal();
ELSE
CVALS(5):= var5;
END;
END;
IF n>=6 THEN
IF CSTAT(6)==2 THEN
CVALS(6):= defaultVal();
ELSE
CVALS(6):= var6;
END;
END;
IF n>=7 THEN
IF CSTAT(7)==2 THEN
CVALS(7):= defaultVal();
ELSE
CVALS(7):= var7;
END;
END;
IF n>=8 THEN
IF CSTAT(8)==2 THEN
CVALS(8):= defaultVal();
ELSE
CVALS(8):= var8;
END;
END;
IF n>=9 THEN
IF CSTAT(9)==2 THEN
CVALS(9):= defaultVal();
ELSE
CVALS(9):= var9;
END;
END;
IF n>=10 THEN
IF CSTAT(10)==2 THEN
CVALS(10):= defaultVal();
ELSE
CVALS(10):= var10;
END;
END;
IF n>=11 THEN
IF CSTAT(11)==2 THEN
CVALS(11):= defaultVal();
ELSE
CVALS(11):= var11;
END;
END;
IF n>=12 THEN
IF CSTAT(12)==2 THEN
CVALS(12):= defaultVal();
ELSE
CVALS(12):= var12;
END;
END;
IF n>=13 THEN
IF CSTAT(13)==2 THEN
CVALS(13):= defaultVal();
ELSE
CVALS(13):= var13;
END;
END;
IF n>=14 THEN
IF CSTAT(14)==2 THEN
CVALS(14):= defaultVal();
ELSE
CVALS(14):= var14;
END;
END;
IF n>=15 THEN
IF CSTAT(15)==2 THEN
CVALS(15):= defaultVal();
ELSE
CVALS(15):= var15;
END;
END;
IF n>=15 THEN
IF CSTAT(15)==2 THEN
CVALS(15):= defaultVal();
ELSE
CVALS(15):= var15;
END;
END;
IF n>=16 THEN
IF CSTAT(16)==2 THEN
CVALS(16):= defaultVal();
ELSE
CVALS(16):= var16;
END;
END;
IF n>=17 THEN
IF CSTAT(17)==2 THEN
CVALS(17):= defaultVal();
ELSE
CVALS(17):= var17;
END;
END;
IF n>=18 THEN
IF CSTAT(18)==2 THEN
CVALS(18):= defaultVal();
ELSE
CVALS(18):= var18;
END;
END;
IF n>=19 THEN
IF CSTAT(19)==2 THEN
CVALS(19):= defaultVal();
ELSE
CVALS(19):= var19;
END;
END;
IF n>=20 THEN
IF CSTAT(20)==2 THEN
CVALS(20):= defaultVal();
ELSE
CVALS(20):= var20;
END;
END;
IF n=21 THEN
IF CSTAT(121)==2 THEN
CVALS(21):= defaultVal();
ELSE
CVALS(21):= var21;
END;
END;
FOR pp FROM 1 TO n DO
IF CSTAT(pp)==0 THEN
IF CVALS(pp)<>prevals(pp) THEN
CSTAT(pp):=1;
END;
END;
END;
solveIterate(idx);
RETURN 1;
END;
//---------------------------------------------------------------
// Entry point for the solve process (called from the listSets() menu)
//---------------------------------------------------------------
solveSet(idx)
BEGIN
LOCAL eqs,cont,n,pp;
eqs:=setEqs(idx);
IF SIZE(eqs)==0 THEN
IF language=="english" THEN
MSGBOX("This set has no equations.");
ELSE
MSGBOX("Este set não tem equações.");
END;
RETURN;
END;
CVARS:=getSetVariables(idx);
n:=MIN(SIZE(CVARS),21);
IF n==0 THEN
IF language=="english" THEN
MSGBOX("No variables found in this set's equations.");
ELSE
MSGBOX("Não há variáveis neste set de equações.");
END;
RETURN;
END;
CVALS:=MAKELIST(defaultVal(),pp,1,n,1);
CSTAT:=MAKELIST(0,pp,1,n,1);
cont:=1;
WHILE cont==1 DO
cont:=solveScreen(idx);
END;
END;
//---------------------------------------------------------------
// List Sets — highlight a set from a scrollable list
//---------------------------------------------------------------
listSets()
BEGIN
LOCAL names,sel,action,n;
IF SIZE(EQSETS)==0 THEN
IF language=="english" THEN
MSGBOX("No equation sets exist.");
ELSE
MSGBOX("Não há nenhum set de equações.");
END;
RETURN;
END;
sel:=0;
REPEAT
names:=getSetNames();
n:=SIZE(names);
IF language=="english" THEN
names(n+1):="Back to Main Menu";
CHOOSE(sel,"Select a Set",names);
ELSE
names(n+1):="Voltar ao menú principal";
CHOOSE(sel,"Seleccione um set",names);
END;
IF sel<>0 AND sel<>n+1 THEN
action:=0;
REPEAT
IF language=="english" THEN
CHOOSE(action,"Set: "+setName(sel),"Solve","View","Edit","Back to List");
ELSE
CHOOSE(action,"Set: "+setName(sel),"Resolver","Ver","Editar","Voltar à lista");
END;
IF action==1 THEN solveSet(sel); END;
IF action==2 THEN viewEquations(sel); END;
IF action==3 THEN setSubMenu(sel); END;
UNTIL action==4 OR action==0;
END;
UNTIL sel==0 OR sel==n+1;
END;
//---------------------------------------------------------------
// Main MES entry point
//---------------------------------------------------------------
EXPORT MES()
BEGIN
LOCAL choice;
initStorage();
choice:=0;
// Clear Terminal screen
PRINT();
REPEAT
IF language=="english" THEN
IF verbose==1 THEN
CHOOSE(choice,"Equation Set Manager","List Sets","New Set","Edit Set","Delete Set","Quiet mode", "Change language","Exit");
ELSE
CHOOSE(choice,"Equation Set Manager","List Sets","New Set","Edit Set","Delete Set","Verbose mode", "Change language","Exit");
END;
ELSE
IF verbose==1 THEN
CHOOSE(choice,"Gestor de equações","Listar Sets","Novo Set","Editar Set","Apagar Set", "Modo silencioso", "Mudar linguagem", "Sair");
ELSE
CHOOSE(choice,"Gestor de equações","Listar Sets","Novo Set","Editar Set","Apagar Set", "Modo verboso", "Mudar linguagem", "Sair");
END;
END;
IF choice==1 THEN listSets(); END;
IF choice==2 THEN newSet(); END;
IF choice==3 THEN editSetMenu(); END;
IF choice==4 THEN deleteSet(); END;
IF choice==5 THEN
IF verbose==1 then verbose:=0 ELSE verbose:=1 END;
END;
IF choice==6 THEN
IF language=="english" then language:="portuguese" ELSE language:="english" END;
END;
UNTIL choice==7 OR choice==0;
END;
|