using System;
using System.IO;			// for StreamReader I/O from a file
using System.Windows.Forms; // for RichTextBox

namespace MyNamespace
{
	/// <summary>
	///		XPCalc - Extra Precision Floating-Point Calculator
	///		Developed in TURBO Pascal 5.5 and 6.0, converted to Visual Basic 6
	///		and now in Visual C# .Net
	///
	/// ---------------- *** LEGAL NOTICE: *** ------------------
	///
	/// This program is free software; you can redistribute it and/or modify
	/// it under the terms of the GNU General Public License (GPL) as published
	/// by the Free Software Foundation. cf. the file COPYING.txt.
	///
	/// ------------ *** end of legal notice *** ------------------
	/// </summary>

	// ------- A multiple-precision named signed floating number
	public class MultiN : MultiF
	{
		public string Nm;			// name

		public MultiN()				// initialize with M = 0 and no name
			: base()				// calls MultiSI()
		{
			Nm = "";	// constructor logic
		}

		public MultiN(int nMaxI, string nm)		// initialize with M = nMaxI and new name
			: base(nMaxI)						// calls MultiSI(i)
		{
			Nm = nm;
		}

//		public static void operator = (MultiN left, MultiF right)	// not allowed to overload =
//		{
//			Calc.SetToNM(right, left);
//		}

		public static MultiN operator & (MultiN left, MultiF right)	// use &= for = assignment
		{
			XPCalLst.SetToNM(right, left);
			return left;
		}
	}

	public class Calc
	{
		public Calc(int iMaxDigits)	// constructor logic
		{
			if (iMaxDigits < 49) iMaxDigits = 49;					// size for >= 49 decimal digits
			int iNMax = 1 + (iMaxDigits - 1) / MultiID.muDMax;		// convert from digits to super digits
			Common.nMax = Math.Min(iNMax, MultiID.muNMax);			// fMC <= mMax <= nMax <= muNMax
			new Calc();
		}

		public Calc()	// constructor logic
		// initialize the calculator
		// input: nMax muDMax
		{
			Common.quiet = true;
			new MultiID();				// initialize class MultiID, Multiple precision integer algorithms
			new MultiFD();				// init Multiple-precision floating decimal package
			MultiFD.fGuard = 4 + 7 / MultiID.muDMax;	// guard super-digits in expanded mode
			Common.delim = ",;<=>+-!|*/&:()^@#%\\'\"";		// @ needed for Batch commands	// ,;<=>+-!|*/&:()^@#%\'"
			MultiID.mMax = Common.nMax;						// fMC <= mMax <= nMax <= muNMax
			fMC = (48 / MultiID.muDMax) + 1;
			MultiFD.fTn = (6 / MultiID.muDMax) + 1;
			MultiID.muDpG = 5;
			MultiID.maxDis = Math.Min(1001, MultiID.mMax * MultiID.muDMax); // set max digits to display
			XPCalLst.CheckNMax();
			Common.mList = 1000;
			Common.nList = new MultiN[Common.mList+1];		// create the list of named numbers
			Common.InitN(1, "", 0);							// change unused name at [0] from null to ""
			Common.InitN(1, "X", 1);						// now create and add a named numbers to the list
			Common.cList = 1;								// x=0 on top of list
			Common.iTop = 1;
			Common.lastTop = 0;
			Common.comI = 0;
			xPCIn = 0;
			xPLOut = 0;
			xPNIn = 0;
			xPNOut = 0;
			Common.lrnL = 0;
			degMode = true;
			MultiID.debug = false;
			MultiID.diagOn = false;
			MultiID.timeIt = false;
			Common.autoD = true;
			MultiFD.scieN = false;
			Common.echoB = true;
			Common.exX = 0;
			Common.prSt = "";
			Common.oldField = "";
			Common.noChange = false;
			Common.saveTop = true;
			MultiID.softAbort = false;
			MultiID.baseI = 10;
			MultiID.baseO = 10;
			MultiID.allowFHT = true;	// allow FHT
			MultiID.forceFHT = false;	// but don't force it
			tic = 0.055;				// seconds per DOS clock tick
			nL = Environment.NewLine;
			bernPrev = new MultiF(4);
			new Common();				// initialize class Common
			new FHTMult();				// initialize class FHTMult
			new XIMult();				// initialize class XIMult
			new NPrimes();				// initialize class NPrimes
			new PrimeFA();				// initialize class PrimeFA
			new MultiPi();				// initialize class MultiPi
			new XICommon();				// initialize class XICommon
			new XPCalLst();				// initialize class XPCalLst
			Common.running = true;
			Common.quiet = false;
			CalReadCode("AutoExec.XPC");
			Common.quiet = true;
		} // Calc

		public static void CalSave() // save all values on list to disk files and make
									 // file Restore.XPC for restoring them
		{
			StreamWriter outF; // text file, for Restore.XPC
			int current;
			string fName;
			int n;
			string st;
			string savDir = Environment.CurrentDirectory.ToString();
			Directory.SetCurrentDirectory(Common.homeDir);
			if (Common.ChkWrite(out outF, "Restore.XPC", ""))
			{
				MultiID.WriteLn(null, outF, "@Echo Off");
				MultiID.WriteLn(null, outF, "Rem  Start of file Restore.XPC");
				current = Common.cList;
				n = 10000;
				while (current != 0)
				{
					fName = n.ToString();
					fName = "Save" + fName.Substring(1, 4) + ".XPN";
					MultiID.WriteLn(null, outF, "ReadN(\"" + fName + "\")");
					current--;
					n++;
				}
				MultiID.WriteLn(null, outF, Common.nList[Common.iTop].Nm + "=");
				MultiID.WriteLn(null, outF, "Rem  End of file Restore.XPC");
				if (Common.echoB) { st = "On"; } else { st = "Off"; }
				MultiID.WriteLn(null, outF, "Echo " + st);
				outF.Close();
				if (!Common.quiet) MultiID.WriteLn("File Restore.XPC closed");
				current = Common.cList;
				while (current != 0)
				{
					n--;
					fName = n.ToString();
					fName = "Save" + fName.Substring(1, 4) + ".XPN";
					CalWriteN(fName, current);
					current--;
				}
			}
			Directory.SetCurrentDirectory(savDir);
		}

		public static void ChkResSav(int resSav, string fName)
		// check for Restore, Save, or Run procedure
		{
			if (resSav == 1) // restore
			{
				CalReadConfig();
				Common.RestoreHist();
				bool saveSaveTop = Common.saveTop; // don't change LastTop after it is read back in
				Common.saveTop = false;
				CalReadCode("Restore.XPC");
				Common.saveTop = saveSaveTop;
			}
			else if (resSav == 2) // save
			{
				CalWriteConfig();
				Common.SaveHist();
				CalSave();
			}
			else if (resSav == 3) // run
			{
				CalReadCode(fName);
			}
		}

		public static void ClearN(int zI) // set value = 0
		{
			MultiID.ClearSI(Common.nList[zI]);
			NormN(zI);
			Common.nList[zI].C = 0;
		}

		public static void SetToN(MultiF x, int zI) // z = x, resized
		// copy everything but .Nm name
		{
			XPCalLst.SetToNM(x, Common.nList[zI]);
		}

		public static void SetToN(MultiSI x, int zI) // z = x, resized
		// copy everything but .Nm name
		{
			XPCalLst.SetToNM(x, Common.nList[zI]);
		}

		public static void SetToII(int xI, int zI) // z = x
		// copy everything but .Nm name
		{
			XPCalLst.SetToNM(Common.nList[xI], Common.nList[zI]);
		}

		public static void NormN(int zI) // normalize number indexed by zI on the list
		{
			XPCalLst.NormNM(Common.nList[zI]);
		}

		public static void ValueN10(string st, out int i, int zI)
		// convert a base 10 String to z, returns i = # of character used
		// allows st to be a literal, muErr set true if overflow
		{
			int saveBaseI = MultiID.baseI;
			MultiID.baseI = 10;
			ValueN(st, out i, zI);
			MultiID.baseI = saveBaseI;
		}

		public static void ValueN(string st, out int i, int zI)
		// convert String to z, returns i = number of character used
		// allows st to be a literal, muErr set true if overflow
		{
			int j;
			MultiF t = new MultiF();
			bool saveExp = MultiFD.expanded;
			int saveFMC = fMC;
			int saveMMax = MultiID.mMax;
			XPCalLst.Expand();
			j = 2 + st.Length / MultiID.muDMax;
			if (MultiID.baseI != 10) j = fMC;
			if (j < 37) j = 37;
			MultiFD.ReSizeF(j, t);		// need large Temp to prevent integer value overflow
			MultiFD.ValueF(st, out i, t);
			SetToN(t, zI);
			MultiFD.DoneF(t);
			MultiFD.expanded = saveExp;
			fMC = saveFMC;
			MultiID.mMax = saveMMax;
			NormN(zI);
		} // ValueN

		public static void WriteNV(RichTextBox outB, StreamWriter outF, MultiN x, ref int tot, int width)
		// output x name + V and a new line. x not modified
		{
			MultiID.WriteT(outB, outF, x.Nm + " =", ref tot, width);
			if (outB == null)
				MultiID.WriteTLn2(outB, outF, "", ref tot, width);
			else
				MultiID.WriteT(outB, outF, " ", ref tot, width);
			MultiFD.WriteF(outB, outF, x, ref tot, width);
		}

		public static void WriteNumLn(MultiN x, ref int tot)
		// output x value and a new line. x not modified
		{
			MultiFD.WriteFLn(x, ref tot);
		}

		public static void CalSMan(int zI)
		// set current number of digits in a result
		{
			double db;
			int saveFMC;
			saveFMC = fMC;
			MultiFD.GetDbInF(out db, 0, Int32.MaxValue, Common.nList[zI]);
			db = 1 + (db - 1) / MultiID.muDMax;		// set for at least N decimal digits
			fMC = (int)db;
			XPCalLst.CheckNMax();
			if (fMC < saveFMC) ListSetM();
			if (fMC > saveFMC) XPCalLst.YankCon();
		}

		public static void ListSetM() // for all items, reduce M to fMC if greater than fMC
		{
			for (int cI = 1; cI <= Common.cList; cI++)
			{
				if (Common.nList[cI].M > fMC)
				{
					NormN(cI); // re-dimension the .V vector
				}
			}
		}

		public static bool GetFName(ref string st)
		// get file name from command line
		// if first parm ends in .XPC, it is changed to Run("... .XPC")
		// if first parm ends in .XPN, it is changed to ReadN("... .XPN")
		{
			bool bGetFName = false;
			int i = st.Length;
			if (i > 4)
			{
				string ext = st.Substring(i - 4, 4);
				ext = ext.ToUpper();
				if (ext == ".XPC")
				{
					st = "Run(\"" + st + "\")";
					bGetFName = true;
				}
				else if (ext == ".XPN")
				{
					st = "ReadN(\"" + st + "\")";
					bGetFName = true;
				}
			}
			if (!bGetFName) st = "";
			return bGetFName;
		}

		public static void TestExpanded()
		{
			if (MultiFD.expanded)
			{
				MultiID.WriteLn("Error: Expanded precision left on");
				if (fMC > MultiFD.fMCB)
				{
					MultiID.WriteLn("Error: fMC > basic fMC");
				}
				MultiID.WriteLn();
				MultiFD.expanded = false;
				fMC = MultiFD.fMCB;
				MultiID.mMax = MultiFD.mMaxB;
			}
		}

		public static bool UnsignedConst(ref string st, int zI)
		// do an Unsigned Constant, Must input number like F... as 0F...
		{
			int i;
			char ch;
			i = 0;
			if (i < st.Length && st[0] == '.') i++;
			if (i < st.Length)
			{
				ch = st[i];
				if (ch >= '0' && ch <= '9')
				{
					Common.EnterN(ref st, zI);
					return true;
				}
			}
			return false;
		}

		public static bool Constant(ref string st, int zI)
		// do a constant, Input number like F... as 0F...
		{
			char ch;
			int i = 0;
			string maxD = MultiID.MaxDig(MultiID.baseI);		// max Input digit "1" to "Z"
			if ( st != "" && (st[0] == '+' || st[0] == '-' ||
								st[0] == '.') ) i++;
			if (i >= st.Length) return false;
			ch = st[i];
			if (ch >= '0' && ch <= '9' && ch <= maxD[0])
			{
				Common.EnterN(ref st, zI);
				return true;
			}
			return false;
		}

		public static bool AFunction(ref string st, int zI) // do a Function
		{
			int tI;				// temp for the 1st argument of a function
			int t2I;			// temp for the 2nd argument of a function
			int t3I;			// temp for the 3rd argument of a function
			int args = 1;
			string name = Common.GetField(ref st);
			int i = name.Length;
			if (i == 0 || i == st.Length || st[i] != '(') return false;
			Common.DelNPBls(ref st, 1 + i);
			Common.InitNAdd(1, "AFunction-tI", out tI);
			Common.InitNAdd(1, "AFunction-t2I", out t2I);
			Common.InitNAdd(1, "AFunction-t3I", out t3I);
			if (!Expression(ref st, tI))
			{
				Common.ReportSin("Error in function's argument: " + name + "(|", ref st);
				args = 0;
			}
			else
			{
				if (st != "" && (st[0] == '\'' || st[0] == ','))
				{
					Common.DelNPBls(ref st, 1);
					args = 2;
					if (!Expression(ref st, t2I))
					{
						Common.ReportSin("Error in function's 2nd argument: " + name + "(..., |", ref st);
						ClearN(t2I);
						args = 1;
					}
					else
					{
						if (st != "" && (st[0] == '\'' || st[0] == ','))
						{
							Common.DelNPBls(ref st, 1);
							args = 3;
							if (!Expression(ref st, t3I))
							{
								Common.ReportSin("Error in function's 3rd argument: " + name + "(..., |", ref st);
								ClearN(t3I);
								args = 2;
							}
						}
					}
				}
				SetToII(tI, zI);
				ClearN(tI);			// to release memory
				if (st != "" && st[0] == ')') Common.DelNPBls(ref st, 1);
				if (MultiID.muErr)
					args = 0;
				else if (name == "ABS")
					Common.nList[zI].S = false;
				else if (name == "ACOS")
					XPCalLst.RACosN(zI);
				else if (name == "ACOSH")
					XPCalLst.RACosHN(zI);
				else if (name == "ACOT")
					XPCalLst.RACotN(zI);
				else if (name == "ACOTH")
					XPCalLst.RACotHN(zI);
				else if (name == "ACSC")
					XPCalLst.RACscN(zI);
				else if (name == "ACSCH")
					XPCalLst.RACscHN(zI);
				else if (name == "AFIB")
					XPCalLst.RAFibN(zI);
				else if (name == "AGM")
					XPCalLst.MeanCN(Common.nList[zI], Common.nList[t2I], zI);
				else if (name == "ASEC")
					XPCalLst.RASecN(zI);
				else if (name == "ASECH")
					XPCalLst.RASecHN(zI);
				else if (name == "ASIN")
					XPCalLst.RASinN(zI);
				else if (name == "ASINH")
					XPCalLst.RASinHN(zI);
				else if (name == "ATAN")
					XPCalLst.RATanN(zI);
				else if (name == "ATAN2")
					XPCalLst.ATan2N(Common.nList[zI], Common.nList[t2I], zI);
				else if (name == "ATANH")
					XPCalLst.RATanHN(zI);
				else if (name == "BERN")
					Bern(Common.nList[zI], zI);
				else if (name == "BERND")
					XPCalLst.BernD(Common.nList[zI], Common.nList[zI]);
				else if (name == "BERNDL")
					XPCalLst.BernDL(Common.nList[zI], Common.nList[zI]);
				else if (name == "BERNG")
					BernG(Common.nList[zI], zI);
				else if (name == "BERNN")
					XPCalLst.BernN(Common.nList[zI], Common.nList[zI]);
				else if (name == "BERNNL")
					XPCalLst.BernNL(Common.nList[zI], Common.nList[zI]);
				else if (name == "BETA")
					XPCalLst.RBetaN(zI);
				else if (name == "BETAC")
					XPCalLst.BetaCN(Common.nList[zI], Common.nList[t2I], zI);
				else if (name == "BETAL")
					XPCalLst.BetaL(Common.nList[zI], Common.nList[zI]);
				else if (name == "BINO")
					XPCalLst.BinoGN(Common.nList[zI], Common.nList[t2I], zI);
				else if (name == "BINOS")
				{
					XPCalLst.RIntSIN(zI);
					XPCalLst.RIntSIN(t2I);
					XICommon.BinoS(Common.nList[zI], Common.nList[t2I], Common.nList[zI]);
					NormN(zI);
				}
				else if (name == "CHIN")
				{
					XPCalLst.RIntSIN(zI);
					XPCalLst.RIntSIN(t2I);
					XICommon.ChinN(zI, t2I, zI);
					NormN(zI);
				}
				else if (name == "CHIN1")
				{
					XPCalLst.RIntSIN(zI);
					XPCalLst.RIntSIN(t2I);
					XICommon.Chin1N(zI, t2I, zI);
					NormN(zI);
				}
				else if (name == "CEILING")
					XPCalLst.RCeilingN(zI);
				else if (name == "COS")
					XPCalLst.RCosN(zI);
				else if (name == "COSH")
					XPCalLst.RCosHN(zI);		
				else if (name == "COT")
					XPCalLst.RCotN(zI);
				else if (name == "COTH")
					XPCalLst.RCotHN(zI);
				else if (name == "CSC")
					XPCalLst.RCscN(zI);
				else if (name == "CSCH")
					XPCalLst.RCscHN(zI);
				else if (name == "CURT")
					XPCalLst.RCuRtN(zI);
				else if (name == "DIG")
				{
					XPCalLst.RIntSIN(zI);
					XPCalLst.RIntSIN(t2I);
					XICommon.DigN(t2I, zI);
					NormN(zI);
				}
				else if (name == "DIGD")
				{
					XPCalLst.RIntSIN(zI);
					XICommon.DigDN(zI);
					NormN(zI);
				}
				else if (name == "DILOG")
					XPCalLst.DilogN(Common.nList[zI], zI);
				else if (name == "DIVINT")
					XPCalLst.DivIntN(Common.nList[zI], Common.nList[t2I], zI);
				else if (name == "DIVREM")
					XPCalLst.DivRemN(Common.nList[zI], Common.nList[t2I], zI);
				else if (name == "E1")
					XPCalLst.E1N(Common.nList[zI], zI);
				else if (name == "EI")
					XPCalLst.EiN(Common.nList[zI], zI);
				else if (name == "ERF")
					XPCalLst.RErfN(zI);
				else if (name == "ERFC")
					XPCalLst.RErfCN(zI);
				else if (name == "ETA")
					XPCalLst.REtaN(zI);
				else if (name == "EULER")
					Euler(Common.nList[zI], zI);
				else if (name == "EULERG")
					EulerG(Common.nList[zI], zI);
				else if (name == "EULERL")
					XPCalLst.EulerL(Common.nList[zI], Common.nList[zI]);
				else if (name == "EULERN")
					XPCalLst.EulerN(Common.nList[zI], Common.nList[zI]);
				else if (name == "EXP")
					XPCalLst.RExpN(zI);
				else if (name == "EXPL")
					XPCalLst.RExpLN(zI);
				else if (name == "FAC")
					XPCalLst.RFacN(zI);
				else if (name == "FAC2")
					XPCalLst.Fac2N(Common.nList[zI], Common.nList[t2I], zI, false);
				else if (name == "FACM")
					XPCalLst.RFacMBN(zI);
				else if (name == "FACM2")
					XPCalLst.Fac2N(Common.nList[zI], Common.nList[t2I], zI, true);
				else if (name == "FACMS")
					XPCalLst.RFacMBSN(zI);
				else if (name == "FACS")
					XPCalLst.RFacSN(zI);
				else if (name == "FIB")
					XPCalLst.RFibN(zI);
				else if (name == "FLOOR")
					XPCalLst.RFloorN(zI);
				else if (name == "FRAC")
					XPCalLst.RFracN(zI);
				else if (name == "GAM")
					XPCalLst.RGamN(zI);
				else if (name == "GAM1")
					XPCalLst.RGamN1(zI);
				else if (name == "GAML")
					XPCalLst.GamLN(Common.nList[zI], Common.nList[t2I], zI);
				else if (name == "GAMP")
					XPCalLst.GamPN(Common.nList[zI], Common.nList[t2I], zI);
				else if (name == "GAMQ")
					XPCalLst.GamQN(Common.nList[zI], Common.nList[t2I], zI);
				else if (name == "GAMU")
					XPCalLst.GamUN(Common.nList[zI], Common.nList[t2I], zI);
				else if (name == "GCD")
					XPCalLst.GCDN(Common.nList[zI], Common.nList[t2I], zI);
				else if (name == "GCDE")
				{
					XPCalLst.RIntSIN(zI);
					XPCalLst.RIntSIN(t2I);
					XICommon.GCDeN(zI, t2I, zI);
					NormN(zI);
				}
				else if (name == "INT")
					XPCalLst.RIntN(zI);
				else if (name == "INV" && args == 1)
					XPCalLst.RInvN(zI);
				else if (name == "INV")
					XICommon.InvN(zI, t2I, zI);
				else if (name == "ISFIB")
					XPCalLst.RIsFibN(zI);
				else if (name == "ISFIB2")
					XPCalLst.RIsFib2N(zI);
				else if (name == "ISSQ")
				{
					if (Common.nList[zI].S || Common.nList[zI].C < 0)
						SetToN(MultiFD.fZero, zI);
					else
					{
						XPCalLst.RIntSIN(zI);
						PrimeFA.IsSq(zI);
						NormN(zI);
					}
				}
				else if (name == "KRON")
				{
					XPCalLst.RIntSIN(zI);
					XPCalLst.RIntSIN(t2I);
					PrimeFA.KronSI(Common.nList[zI], Common.nList[t2I], Common.nList[zI]);
					NormN(zI);
				}
				else if (name == "LAM")
					XPCalLst.RLambdaN(zI);
				else if (name == "LCM")
					XPCalLst.LCMN(Common.nList[zI], Common.nList[t2I], zI);
				else if (name == "LERCH")
					XPCalLst.Lerch(Common.nList[zI], Common.nList[t2I], Common.nList[t3I], false, zI);
				else if (name == "LERCH1")
					XPCalLst.Lerch1(Common.nList[zI], Common.nList[t2I], Common.nList[t3I], false, zI);
				else if (name == "LERCH2")
					XPCalLst.Lerch2(Common.nList[zI], Common.nList[t2I], Common.nList[t3I], false, zI);
				else if (name == "LERCHT")
					XPCalLst.Lerch(Common.nList[zI], Common.nList[t2I], Common.nList[t3I], true, zI);
				else if (name == "LERCHT1")
					XPCalLst.Lerch1(Common.nList[zI], Common.nList[t2I], Common.nList[t3I], true, zI);
				else if (name == "LERCHT2")
					XPCalLst.Lerch2(Common.nList[zI], Common.nList[t2I], Common.nList[t3I], true, zI);
				else if (name == "LI")
					XPCalLst.LiN(Common.nList[zI], zI);
				else if (name == "LN")
					XPCalLst.RLnN(zI);
				else if (name == "LNL")
					XPCalLst.RLnLN(zI);
				else if (name == "LOG")
					XPCalLst.RLogN(zI);
				else if (name == "LOP")
					XPCalLst.RLopN(zI);
				else if (name == "MAG")
					XPCalLst.MagN(Common.nList[zI], Common.nList[t2I], zI);
				else if (name == "MAX")
					XPCalLst.MaxN(Common.nList[zI], Common.nList[t2I], zI);
				else if (name == "MEANC")
					XPCalLst.MeanCN(Common.nList[zI], Common.nList[t2I], zI);
				else if (name == "MEQ")
				{
					XPCalLst.RIntSIN(zI);
					XICommon.MersenneEq(zI);
					NormN(zI);
				}
				else if (name == "MIN")
					XPCalLst.MinN(Common.nList[zI], Common.nList[t2I], zI);
				else if (name == "MOD")
					XPCalLst.RModN(Common.nList[t2I], zI);
				else if (name == "MORD")
				{
					XPCalLst.RIntSIN(zI);
					XPCalLst.RIntSIN(t2I);
					PrimeFA.MorderSI(Common.nList[zI], Common.nList[t2I], Common.nList[zI]);
					NormN(zI);
				}
				else if (name == "MPG")
				{
					XPCalLst.RIntSIN(zI);
					XICommon.MersennePG(zI);
					NormN(zI);
				}
				else if (name == "MPP")
				{
					XPCalLst.RIntSIN(zI);
					XICommon.MersennePP(zI);
					NormN(zI);
				}
				else if (name == "MPRIME")
				{
					XPCalLst.RIntSIN(zI);
					XICommon.MersenneP(zI);
					NormN(zI);
				}
				else if (name == "MU")
				{
					XPCalLst.RIntSIN(zI);
					PrimeFA.MoebiusMu(zI);
					NormN(zI);
				}
				else if (name == "NORMC")
					XPCalLst.NormC(Common.nList[zI], Common.nList[t2I], Common.nList[t3I], zI);
				else if (name == "NORMS")
					XPCalLst.NormS(zI);
				else if (name == "P")
				{
					XPCalLst.RIntSIN(zI);
					XICommon.PrimePT(zI);
					NormN(zI);
				}
				else if (name == "PEQ")
				{
					XPCalLst.RIntSIN(zI);
					XICommon.PerfectEq(zI);
					NormN(zI);
				}
				else if (name == "PGT")
				{
					XPCalLst.RIntSIN(zI);
					PrimeFA.findUp = true;
					PrimeFA.PrimeSearch(zI);
					NormN(zI);
				}
				else if (name == "PHI")
				{
					XPCalLst.RIntSIN(zI);
					PrimeFA.PrimePhi(zI);
					NormN(zI);
				}
				else if (name == "PHIL")
				{
					XPCalLst.RIntSIN(zI);
					XPCalLst.RIntSIN(t2I);
					PrimeFA.PhiLN(zI, t2I, zI);
					NormN(zI);
				}
				else if (name == "PI")
				{
					XPCalLst.RIntSIN(zI);
					XICommon.PrimePiT(zI);
					NormN(zI);
				}
				else if (name == "PIL")
				{
					XPCalLst.RIntSIN(zI);
					PrimeFA.PrimePiLT(zI);
					NormN(zI);
				}
				else if (name == "PIL1")
				{
					XPCalLst.RIntSIN(zI);
					PrimeFA.PrimePiL1(zI);
					NormN(zI);
				}
				else if (name == "PIM")
				{
					XPCalLst.RIntSIN(zI);
					PrimeFA.PrimePiM(zI);
					NormN(zI);
				}
				else if (name == "PLT")
				{
					if (Common.nList[zI].C < 0)
						XPCalLst.RAdd1N(1, zI);
					XPCalLst.RIntSIN(zI);
					PrimeFA.findUp = false;
					PrimeFA.PrimeSearch(zI);
					NormN(zI);
				}
				else if (name == "PNG")
				{
					XPCalLst.RIntSIN(zI);
					XICommon.PerfectNG(zI);
					NormN(zI);
				}
				else if (name == "POLYLOG")
					XPCalLst.PolylogN(Common.nList[zI], Common.nList[t2I], zI);
				else if (name == "POW")
					XPCalLst.RPowN(Common.nList[t2I], zI);
				else if (name == "POWM")
					XPCalLst.RPowMN(Common.nList[t2I], zI);
				else if (name == "PRIME")
				{
					XPCalLst.RIntSIN(zI);
					PrimeFA.Prime(zI);
					NormN(zI);
				}
				else if (name == "PRIMO")
				{
					XPCalLst.RIntSIN(zI);
					XICommon.Primorial(zI);
					NormN(zI);
				}
				else if (name == "PRIMR")
				{
					XPCalLst.RIntSIN(zI);
					PrimeFA.PrimR(zI, false);
					NormN(zI);
				}
				else if (name == "PRIMRP")
				{
					XPCalLst.RIntSIN(zI);
					PrimeFA.PrimR(zI, true);
					NormN(zI);
				}
				else if (name == "PRIMRQ")
				{
					XPCalLst.RIntSIN(zI);
					XPCalLst.RIntSIN(t2I);
					PrimeFA.PrimRQ(zI, t2I, zI);
					NormN(zI);
				}
				else if (name == "PSI")
					XPCalLst.RPsiN(zI);
				else if (name == "QUADR")
					XPCalLst.QuadRoot(Common.nList[zI], Common.nList[t2I], Common.nList[t3I], zI);
				else if (name == "REV")
				{
					XPCalLst.RIntSIN(zI);
					XPCalLst.RIntSIN(t2I);
					XICommon.RevN(zI, t2I, zI);
					NormN(zI);
				}
				else if (name == "RI")
					XPCalLst.RiN(Common.nList[zI], zI);
				else if (name == "RINT")
					XPCalLst.RRIntN(t2I, zI);
				else if (name == "RN")
					RRanN(zI);
				else if (name == "ROUND")
					XPCalLst.RRoundN(zI);
				else if (name == "SEC")
					XPCalLst.RSecN(zI);
				else if (name == "SECH")
					XPCalLst.RSecHN(zI);
				else if (name == "SIG")
				{
					XPCalLst.RIntSIN(zI);
					PrimeFA.PrimeSig(zI);
					NormN(zI);
				}
				else if (name == "SIG0")
				{
					XPCalLst.RIntSIN(zI);
					PrimeFA.PrimeSig0(zI);
					NormN(zI);
				}
				else if (name == "SIGN")
				{
					int sign = MultiFD.SignF(Common.nList[zI]);
					MultiFD.SetTo1F(sign, Common.nList[zI]);
					NormN(zI);
				}
				else if (name == "SIN")
					XPCalLst.RSinN(zI);
				else if (name == "SINH")
					XPCalLst.RSinHN(zI);
				else if (name == "SOLVE")
				{
					XPCalLst.RIntSIN(zI);
					XPCalLst.RIntSIN(t2I);
					XPCalLst.RIntSIN(t3I);
					XICommon.SolveN(zI, t2I, t3I, zI);
					NormN(zI);
				}
				else if (name == "SORD")
				{
					XPCalLst.RIntSIN(zI);
					XPCalLst.RIntSIN(t2I);
					PrimeFA.SorderSI(Common.nList[zI], Common.nList[t2I], Common.nList[zI]);
					NormN(zI);
				}
				else if (name == "SQ")
					XPCalLst.RSqN(zI);
				else if (name == "SQFREE")
				{
					XPCalLst.RIntSIN(zI);
					PrimeFA.SqFree(zI);
					NormN(zI);
				}
				else if (name == "SQRT")
					XPCalLst.RSqRtN(zI);
				else if (name == "SQRTREM")
					XPCalLst.RSqRtRemN(zI);
				else if (name == "SUMD")
				{
					XPCalLst.RIntSIN(zI);
					XPCalLst.RIntSIN(t2I);
					XICommon.SumDN(t2I, zI);
					NormN(zI);
				}
				else if (name == "SUMDD")
				{
					XPCalLst.RIntSIN(zI);
					XICommon.SumDDN(zI);
					NormN(zI);
				}
				else if (name == "TAN")
					XPCalLst.RTanN(zI);
				else if (name == "TANH")
					XPCalLst.RTanHN(zI);
				else if (name == "TAU")
				{
					XPCalLst.RIntSIN(zI);
					PrimeFA.PrimeTau(zI);
					NormN(zI);
				}
				else if (name == "TODEG")
					XPCalLst.RToDegN(zI);
				else if (name == "TORAD")
					XPCalLst.RToRadN(zI);
				else if (name == "ZETA")
					XPCalLst.RZetaN(zI);
				else if (name == "ZETAH")
					XPCalLst.ZetaHN(Common.nList[zI], Common.nList[t2I], zI);
				else
				{
					Common.ReportSin("Unknown function: |" + name + "(", ref st);
					args = 0;
				}
			}
			Common.LDelete(t3I);	// delete in reverse order of creation
			Common.LDelete(t2I);
			Common.LDelete(tI);
			if (name == "LERCH" || name == "LERCH1" || name == "LERCH2" ||
				name == "LERCHT" || name == "LERCHT1" || name == "LERCHT2" ||
				name == "NORMC" || name == "QUADR" || name == "SOLVE")
			{
				if (args == 1)
					MultiID.WriteDLn(name + ": 2nd and 3rd argument assumed = 0.0");
				if (args == 2)
					MultiID.WriteDLn(name + ": 3rd argument assumed = 0.0");
			}
			else if (name == "AGM" || name == "ATAN2" || name == "BETAC" ||
				name == "BINO" || name == "BINOS" || name == "CHIN" || name == "CHIN1" || name == "DIG" || name == "DIVINT" || name == "DIVREM" ||
				name == "FAC2" || name == "FACM2" || name == "GAML" ||
				name == "GAMU" || name == "GAMP" || name == "GAMQ" ||
				name == "GCD" || name == "GCDE" || name == "INV" || name == "KRON" || name == "LCM" || name == "MAG" ||
				name == "MAX" || name == "MEANC" || name == "MIN" ||
				name == "MOD" || name == "MORD" || name == "PHIL" || name == "POLYLOG" || name == "POW" ||
				name == "POWM" || name == "PRIMRQ" || name == "REV" || name == "RINT" || name == "SORD" || name == "SUMD" || name == "ZETAH")
			{
				if (args == 1 && name != "REV" && name != "INV")
					MultiID.WriteDLn(name + ": Second argument assumed = 0.0");
				if (args > 2)
					MultiID.WriteDLn(name + ": Only two arguments used");
			}
			else
			{
				if (args > 1)
					MultiID.WriteDLn(name + ": Second argument ignored");
			}
			return true;
		} // AFunction

		public static bool Factor(ref string st, int zI) // do a Factor
		{
			int tI;
			bool zip;
			if (st == "") return false;
			if (UnsignedConst(ref st, zI)) return true;
			if (AFunction(ref st, zI)) return true;
			if (Variable(ref st, out tI))
			{
				SetToII(tI, zI);
				return true;
			}
			if (st != "" && st[0] == '(')
			{
				Common.DelNPBls(ref st, 1);
				if (Expression(ref st, zI))
				{
					if (st != "" && st[0] == ')') Common.DelNPBls(ref st, 1);
					return true;
				}
				else
				{
					Common.ReportSin("Expression expected: (|", ref st);
					return true;
				}
			}
			if (st != "" && st[0] == '!')
			{
				Common.DelNPBls(ref st, 1);
				if (Factor(ref st, zI))
				{
					zip = Common.ZTestN(zI);
					ClearN(zI);
					if (zip) Common.nList[zI].V[0] = 1;
					return true;
				}
				else
				{
					Common.ReportSin("Factor expected: !|", ref st);
					return true;
				}
			}
			return false;
		} // Factor

		public static bool Power(ref string st, int zI) // do a Power
		{
			string sign;
			string op;
			int tI;
			int t2I;
			if (!Factor(ref st, zI)) return false;
			while (true)
			{
				if (st == "") return true;
				op = st.Substring(0, 1);
				if (op != "^") return true;
				Common.DelNPBls(ref st, 1);
				if (st == "") return true;
				sign = st.Substring(0, 1);
				if (sign == "+" || sign == "-")
				{
					Common.DelNPBls(ref st, 1);
					if (st == "") return true;
				}
				else
				{
					sign = "";
				}
				Common.InitNAdd(1, "Power-tI", out tI);
				// 3^3^3 gave (3^3)^3 = 19683, should give 3^(3^3) = 762,55974,84987, fixed
				// by changing Factor to Power on next line 2003-11-22 HJS
				if (Power(ref st, tI))
				{
					if (sign == "-") Common.ChSN(tI);
					Common.InitNAdd(1, "Power-t2I", out t2I);
					if (op == "^")
					{
						XPCalLst.PowN(Common.nList[zI], Common.nList[tI], t2I);
					}
					SetToII(t2I, zI);
					Common.LDelete(t2I);
					NormN(zI);
				}
				else
				{
					Common.ReportSin("Exponent expected:" + "^" + sign + "|", ref st);
				}
				Common.LDelete(tI);
			}
		} // Power

		public static bool Term(ref string st, int zI) // do a Term
		{
			char op;
			int tI;
			int t2I;
			if (!Power(ref st, zI)) return false;
			while (true)
			{
				if (st == "") return true;
				op = st[0];
				if (op != '*' && op != '/' && op != '&' &&
					 op != '@' && op != '#' && op != '%' && op != '\\') return true;
				Common.DelNPBls(ref st, 1);
				Common.InitNAdd(1, "Term-tI", out tI);
				if (!Power(ref st, tI))
				{
					Common.ReportSin("Factor expected: " + op + "|", ref st);
				}
				else
				{
					Common.InitNAdd(1, "Term-t2I", out t2I);
					if (op == '*')
						XPCalLst.MulN(Common.nList[zI], Common.nList[tI], t2I);
					else if (op == '/')
						XPCalLst.DivN(Common.nList[zI], Common.nList[tI], t2I);
					else if (op == '@')
						XPCalLst.ATan2N(Common.nList[zI], Common.nList[tI], t2I);
					else if (op == '#')
						XPCalLst.MagN(Common.nList[zI], Common.nList[tI], t2I);
					else if (op == '%')
						XPCalLst.ModN(Common.nList[zI], Common.nList[tI], t2I);
					else if (op == '\\')
						XPCalLst.DivIntN(Common.nList[zI], Common.nList[tI], t2I);
					else if (op == '&')
					{
						if (!Common.ZTestN(zI) && !Common.ZTestN(tI))
						{
							Common.nList[t2I].V[0] = 1;
						}
					}
					SetToII(t2I, zI);
					Common.LDelete(t2I);
				}
				Common.LDelete(tI);
			}
		} // Term

		public static bool SimpExpr(ref string st, int zI)
		// do a Simple Expression
		{
			char sign = ' ';
			bool met;
			string op;
			string op2;
			int tI;
			if (st != "") sign = st[0];
			if (sign == '+' || sign == '-')
			{
				Common.DelNPBls(ref st, 1);
			}
			else
			{
				sign = ' ';
			}
			if (!Term(ref st, zI))
			{
				if (sign == ' ') return false;
				Common.ReportSin("Term expected: " + sign + "|", ref st);
				return true;
			}
			if (sign == '-') Common.ChSN(zI);
			while (true)
			{
				if (st == "") return true;
				op = st.Substring(0, 1);
				op2 = "";
				if (st.Length > 1) op2 = st.Substring(0, 2);
				if (op != "+" && op != "-" && op != "|" && op2 != "--")
					return true;
				if (op2 == "--")
				{
					Common.DelNPBls(ref st, 2);
					op = op2;
				}
				else
				{
					Common.DelNPBls(ref st, 1);
				}
				Common.InitNAdd(1, "SimpExpr-tI", out tI);
				if (!Term(ref st, tI))
				{
					Common.ReportSin("Term expected: " + op + "|", ref st);
				}
				else
				{
					if (op == "+") XPCalLst.RAddN(Common.nList[tI], zI);
					else if (op == "-")	XPCalLst.RSubN(Common.nList[tI], zI);
					else if (op == "|")
					{
						met = !Common.ZTestN(zI) || !Common.ZTestN(tI);
						ClearN(zI);
						if (met) Common.nList[zI].V[0] = 1;
					}
					else if (op == "--")
					{
						bool saveExp = MultiFD.expanded;
						int saveFMC = fMC;
						int saveMMax = MultiID.mMax;
						XPCalLst.Expand();
						RepUnitN(tI);
						XPCalLst.RMulN(Common.nList[tI], zI);
						MultiFD.expanded = saveExp;
						fMC = saveFMC;
						MultiID.mMax = saveMMax;
						NormN(zI);
					}
				}
				Common.LDelete(tI);
			}
		} // SimpExpr

		public static bool Variable(ref string st, out int zI) // do a Variable
		// passed By Value is default, st is input and output, zI is output, points to Variable on the list
		{
			bool state;
			int i;
			int iL;
			char ch = ' ';
			string name;
			state = false;
			zI = 0;							// zI = 0 for returns of false
			name = Common.GetField(ref st);
			iL = name.Length;
			if (iL > 0) ch = name[0];
			if (ch >= 'A' && ch <= 'Z')		// first ch is a letter
			{
				i = 0;
				state = true;
				while (i < iL-1)
				{
					i++;
					ch = name[i];
					if ( (ch >= 'A' && ch <= 'Z') ||
						(ch >= '0' && ch <= '9') )		// and all ch are numbers or letters
					{
						; // noOp
					}
					else
					{
						state = false;		// not a Variable name
						i = iL;				// exit while
					}
				}
			}
			if (state)
			{
				Common.LFind(name, out zI);		// search the list, if there, point to it
				if (zI == 0)				// if not on the list
				{
					if (name == "CAT")
						Cat(out zI);
					else if (name == "EE")
						Ee(out zI);
					else if (name == "EULERC")
						EulerC(out zI);
					else if (name == "LN10")
						Ln10(out zI);
					else if (name == "PHI")
						Phi(out zI);
					else if (name == "PHIP")
						PhiP(out zI);
					else if (name == "PI")
						Pi(out zI);
					else if (name == "UBIQ")
						Ubiq(out zI);
					else
					{
						name = st.Substring(0, iL); // get original lower case letters
						Common.LFindAdd(name, out zI);		// add it to the list if not there and point to it
					}
				}
				Common.DelNPBls(ref st, iL);
			}
			return state;
		} // Variable

		public static void RepUnitN(int zI) // z = 111...111, 1 repeated z times in baseO
		// R2, R19, R23, R317, and R1031 are the only known repunit primes in base 10
		// the next one is larger than R16500
		// Repunit n = (base^n - 1)/(base-1), The Output base is used for this
		// if n = z is not an integer > 0, z = (base^z - 1)/(base-1)
		{
			MultiF b = new MultiF(1);
			MultiFD.SetTo1F(MultiID.baseO, b);			// b = base
			XPCalLst.PowN(b, Common.nList[zI], zI);		// z = base ^ z
			XPCalLst.RAdd1N(-1, zI);					// z = z - 1
			XPCalLst.RDiv1N(MultiID.baseO - 1, zI);		// z = z / (base - 1)
			MultiFD.DoneF(b);
			NormN(zI);
		} // RepUnitN

		public static void RRanN(int zI) // z = random number from seed z
		{
			int rNA;
			int rNC;		// constants for the random number generator
			int i;
			int saveFMC;
			int aN = (34 / MultiID.muDMax) + 1;		// Super digits in rNA
			if (fMC < aN)
			{
				MultiID.MuWriteErr("Cannot generate random numbers with digits in mantissa < 35");
				return;
			}
			Common.LFind("RNA", out rNA);
			if (rNA > 0)
			{
				if (Common.nList[rNA].N < aN)
					rNA = 0;
			}
			Common.LFind("RNC", out rNC);
			if (rNC > 0)
			{
				if (Common.nList[rNC].N < aN)
					rNC = 0;
			}
			if (rNA == 0)
			{
				Common.LFindAdd("RNA", out rNA);
				ValueN10("1843624,8305725,0753463,7429192,0765341", out i, rNA);
			}
			if (rNC == 0)
			{
				Common.LFindAdd("RNC", out rNC);
				ValueN10("8634647,9732047,9456723,8254463,9625443", out i, rNC);
			}
			saveFMC = fMC;
			fMC = 2 * aN;
			XPCalLst.FracN(Common.nList[zI], zI);
			Common.nList[zI].C += aN;
			if (MultiID.muDMax == 8)	// tested for 4, 7, and 8
				MultiFD.RDiv1F(100000, Common.nList[zI]);
			else if (MultiID.muDMax == 4)
				MultiFD.RDiv1F(10, Common.nList[zI]);
			XPCalLst.IntN(Common.nList[zI], zI);
			XPCalLst.RMulN(Common.nList[rNA], zI);
			XPCalLst.RAddN(Common.nList[rNC], zI); // z = (rNA * z + rNC) % (baseM^aN)
			Common.nList[zI].S = false;
			Common.nList[zI].C -= aN;
			if (MultiID.muDMax == 8)
				XPCalLst.RMul1N(100000, zI);
			else if (MultiID.muDMax == 4)
				XPCalLst.RMul1N(10, zI);
			XPCalLst.FracN(Common.nList[zI], zI);
			int rNI;								// update seed for the N command
			Common.LFindAdd("RN", out rNI);
			if (rNI != zI) SetToN(Common.nList[zI], rNI);
			fMC = saveFMC;
		} // RRanN

		public static void RanN(int zI) // z = random number from seed RN
		{
			int rNI;			// random number
			if (fMC < (34 / MultiID.muDMax) + 1)
			{
				int i = 0;
				RRanN(i);		// call RRanN for error message
				return;
			}
			Common.LFindAdd("RN", out rNI);
			RRanN(rNI);			// rN = (rNA * rN + rNC) % (base^5)
			SetToII(rNI, zI);
		}

		public static bool Expression(ref string st, int zI) // do an Expression
		{
			string op;
			string op2;
			int tI;
			int sign;
			bool met;
			if (!SimpExpr(ref st, zI)) return false;
			if (st == "") return true;
			op = st.Substring(0, 1);
			op2 = "";
			if (st.Length > 1) op2 = st.Substring(0, 2);
			if (op != "<" && op != "!" && op != "=" && op != ">")
				return true;
			if (op2 == "==" || op2 == "<=" || op2 == "<>" || op2 == "!=" || op2 == ">=")
			{
				Common.DelNPBls(ref st, 2);
			}
			else
			{
				if (op == "!") return true;
				Common.DelNPBls(ref st, 1);
			}
			Common.InitNAdd(1, "Expression-tI", out tI);
			if (!SimpExpr(ref st, tI))
			{
				Common.ReportSin("Simple Expression expected: " + op2 + "|", ref st);
			}
			else
			{
				sign = MultiFD.CompFF(Common.nList[tI], Common.nList[zI]);
				if (op2 == "<=")
					met = (sign <= 0);
				else if (op2 == "<>" || op2 == "!=")
					met = (sign != 0);
				else if (op2 == ">=")
					met = (sign >= 0);
				else if (op2 == "==")
					met = (sign == 0);
				else if (op == "<")
					met = (sign < 0);
				else if (op == "=")
					met = (sign == 0);
				else if (op == ">")
					met = (sign > 0);
				else
					met = false;	// should not get here
				ClearN(zI);
				if (met) Common.nList[zI].V[0] = 1;	// n is initially zero
			}
			Common.LDelete(tI);
			return true;
		} // Expression

		public static void ReadFNmB(StreamReader inF, out bool oK, int zI, ref string fName, string st)
		// input st is a possible initial input line
		// read in z (baseI) from a file, oK = true; if no I/O errors
		{
			int i;
			char ch;
			bool fini = false;
			string stN = "";
			string stE = "";
			int need = Int32.MaxValue;
			string maxD = MultiID.MaxDig(MultiID.baseI);
			oK = true;
			try
			{
				do
				{
					if (st == "") st = inF.ReadLine();	// get next line of input
					if (st == null) break;				// null => EOF
					if (stE == "" && stN == "")
					{
						i = st.IndexOf("E+");
						if (i < 0) i = st.IndexOf("E-");
						if (i < 0) i = st.IndexOf("`+");
						if (i < 0) i = st.IndexOf("`-");
						if (i >= 0)
						{
							stE = st.Substring(i);
							need = (int)((fMC + 2) * MultiID.muDMax / Math.Log10(MultiID.baseI));
							st = "";
						}
					}
					int iL = st.Length;
					for (i = 0; i < iL; i++)
					{
						ch = Char.ToUpper(st[i]);
						if (ch >= '0' && ch <= maxD[0] && (ch <= '9' || ch >= 'A')) // get value
							stN += ch;
						else if (ch == '.' || ch == '+' || ch == '-' || ch == '`' || ch == 'E')
						{
							if (ch == '`' || ch == 'E')
							{
								stN += st.Substring(i);
								break;	// exit for
							}
							else
							{
								stN += ch;
							}
						}
						else if (ch != ',' && ch != ' ')
						{
							fini = true;
							break;		// stop if garbage after number
						}
					}
					st = "";			// and ignore garbage before number
					MultiID.MuInterrupt();
				}
				while (!fini && !MultiID.muAbort && !(stN.Length > need)); // not fini ...
				ValueN(stN + stE, out i, zI);
			}
			catch (Exception ex)
			{
				// trap read error
				MultiID.WriteLn(" Read error file \"" + fName + '"');
				Common.WCurDir(fName);
				Common.ReportError("ReadFNmB", ex.Message);
				oK = false;
			}
		} // ReadFNmB

		public static void ReadFNm10(StreamReader inF, out bool oK, int zI, ref string fName, string st)
		// read in z (base 10) from an already opened file, oK = true if no I/O errors
		{
			int saveFMC;
			string st4;
			bool fini;
			bool vStarted;		// false if still looking for first digit
			bool sFound;		// false if still looking for a sign
			bool pFound;
			bool eFound;
			bool sign;
			int tI;
			int i;
			int j;
			int k;
			int jB;
			int jA;				// HJS 91/08/19
			decimal ee = 0;		// = 0 to prevent "Use of unassigned local variable 'ee'" build error
			decimal dI;
			int d1;
			int baseIS = MultiID.baseI;
			MultiID.baseI = 10; // read file in base 10 format
			saveFMC = fMC;
			fMC = Math.Max(fMC + 1, 1 + 255 / MultiID.muDMax);
			ClearN(zI);
			Common.InitNAdd(fMC, "ReadFNm10-tI", out tI);
			fini = false;
			vStarted = false;
			sFound = false;
			pFound = false;
			eFound = false;
			sign = false;
			jB = 0;
			jA = 0;
			oK = false;
			try
			{
				do
				{
					if (st == "") st = inF.ReadLine();	// get next line of input
					if (st == null) break;				// null => EOF
					i = 0;
					while (true)
					{
						i = st.IndexOf(' ', i);
						if (i >= 0) st = st.Remove(i, 1); // delete all blanks
						else break;
					}
					i = 0;
					while (true)
					{
						i = st.IndexOf(',', i);
						if (i >= 0) st = st.Remove(i, 1);// delete all commas
						else break;
					}
					if (st != "")
					{
						if (!sFound && !vStarted)
						{
							if (st[0] == '+' || st[0] == '-')
							{
								sFound = true;
								vStarted = true;
								if (st[0] == '-') sign = true;
								MultiID.Delete(ref st, 0, 1);
							}
						}
						DoDigits(ref zI, ref tI, ref jA, ref jB, ref vStarted, ref pFound, ref st);
						if (!pFound && (st[0] == '.'))
						{
							pFound = true;
							vStarted = true;
							MultiID.Delete(ref st, 0, 1);
							DoDigits(ref zI, ref tI, ref jA, ref jB, ref vStarted, ref pFound, ref st);
						}
						st4 = "";
						if (st.Length >= 4) st4 = st.Substring(0, 4).ToUpper();
						if (st4 == "PAGE")
						{
							st = st.Substring(0, 4) + " " + st.Substring(4); // insert " " after "Page"
							if (!Common.quiet) MultiID.WriteLn(st);
							st = "";
						}
						if (eFound)
						{
							if (jB + jA > saveFMC * (int)MultiID.muDMax) fini = true;
						}
						else
						{
							i = 0;
							st = st.ToUpper();
							while (i < st.Length - 1)
							{
								if (st[i] == 'E' || st[i] == '`')
								{
									MultiID.Delete(ref st, 0, i + 1);
									i = -1;
									if ( (st[0] >= '0' && st[0] <= '9') ||
										(st.Length >= 2 &&
										(st[0] == '+' || st[0] == '-') &&
										st[1] >= '0' && st[1] <= '9') )
									{
										MultiID.ValueSI(st, out j, Common.nList[tI]);
										MultiID.GetDeSI(out ee, Common.nList[tI]);
										MultiID.Delete(ref st, 0, j);
										eFound = true;
										if (vStarted) fini = true;
										break; // exit while
									}
								}
								i++;
							}
						}
					}
					MultiID.MuInterrupt();	// allow for abort
					if (MultiID.statReq)
					{
						st = "ReadFNm10: Digits input = " + Common.nList[zI].N * MultiID.muDMax;
						MultiID.WriteLn(st);
						MultiID.statReq = false;
					}
					st = "";
				}
				while (!fini && !MultiID.muAbort);
				if (eFound)
				{
					dI = Decimal.Floor(ee / MultiID.muDMax);
					if (dI + Common.nList[zI].C > Int64.MaxValue)
					{
						MultiID.MuWriteErr("Floating Value overflow, continuing...");
						ClearN(zI);		// abort
						fMC = saveFMC;
						MultiID.baseI = baseIS;
						oK = false;
						return;
					}
					if (dI + Common.nList[zI].C < -Int64.MaxValue)
					{
						ClearN(zI);
						fMC = saveFMC;
						MultiID.baseI = baseIS;
						oK = true;
						return;
					}
					Common.nList[zI].C = (long)(dI + Common.nList[zI].C);
					k = (int)(ee - dI * MultiID.muDMax);
					d1 = 1;
					for (i = 1; i <= k; i++)
						d1 *= 10;
					XPCalLst.RMul1N(d1, zI);
				}
				Common.LDelete(tI);
				fMC = saveFMC;
				MultiID.baseI = baseIS;
				Common.nList[zI].S = sign;
				NormN(zI);
				oK = true;
				return;
			}
			catch (Exception ex)
			{
				// trap read error
				MultiID.WriteLn(" Read error file \"" + fName + '"');
				Common.WCurDir(fName);
				Common.ReportError("ReadFNm10", ex.Message);
				Common.LDelete(tI);
				ClearN(zI);
				fMC = saveFMC;
				MultiID.baseI = baseIS;
				oK = false;
			}
		} // ReadFNm10

		public static void DoDigits(ref int zI, ref int tI, ref int jA, ref int jB, ref bool vStarted, ref bool pFound, ref string st)
		// part of ReadFNm10
		{
			int ii;
			int j;
			int d1;
			if (st == "") return;
			char ch = st[0];
			if (ch < '0' || ch > '9') return;
			vStarted = true;
			MultiFD.ClearF(Common.nList[tI]); // ClearN tI not correct it normalizes
			if (pFound)
			{
				MultiID.ValueSI10(st, Common.nList[tI]);
				j = st.Length;
				st = "";
			}
			else
			{
				MultiID.ValueSI(st, out j, Common.nList[tI]);
				MultiID.Delete(ref st, 0, j);
			}
			if (!pFound)
			{
				jB += j;
				Common.nList[zI].C = Common.nList[zI].C + (j / MultiID.muDMax);
				d1 = 1;
				int iL = j % MultiID.muDMax;
				for (ii = 1; ii <= iL; ii++)
					d1 *= 10;
				if (d1 != 1) XPCalLst.RMul1N(d1, zI);
			}
			else
			{
				jA += j;
				Common.nList[tI].C = Common.nList[tI].C - (jA / MultiID.muDMax);
				j = jA % MultiID.muDMax;
				if (j != 0)
				{
				d1 = 1;
				int iL = MultiID.muDMax - j;
				for (ii = 1; ii <= iL; ii++)
					d1 *= 10;
				if (d1 != 1)
				{
					MultiFD.RMul1F(d1, Common.nList[tI]);
					Common.nList[tI].C = Common.nList[tI].C - 1;
					}
				}
			}
			XPCalLst.RAddN(Common.nList[tI], zI);
			return;
		} // DoDigits

		public static void ReadFNm(StreamReader inF, out string name, out bool oK, int zI, ref string fName)
		// read in z from an already opened file
		// get its name and base from file, oK = true; if no I/O errors
		{
			char ch;
			string st;
			int i;
			int j = 0;
			int baseIS;
			int baseIL = 0;
			string maxD = "9";
			string stN = "";
			bool fini = false;
			oK = false;
			name = "";
			MultiFD.ReSizeF(1, Common.nList[zI]); // z = 0, don't change name
			try
			{
				do
				{
					st = inF.ReadLine();				// get next line of input
					if (st == null) break;				// null => EOF
					if (baseIL == 0)
					{
						j = st.ToUpper().IndexOf("BASE(");	// look for base(xx
						if (j >= 0)
						{
							stN = st.Substring(j + 5, 2);
							if (stN[1] < '0' || stN[1] > '9')
							{
								stN = stN.Substring(0, 1);
								j--;
							}
							if (stN[0] < '0' || stN[0] > '9')
							{
								baseIL = 10;
								st = "";
							}
							else
							{
								baseIL = System.Int32.Parse(stN);
								if (baseIL < 2 || baseIL > 36) baseIL = 10;
								if (st[j+7] == ')') j++;
								MultiID.Delete(ref st, 0, j + 7);
							}
							maxD = MultiID.MaxDig(baseIL);
						}
					}
					if (name == "")					// look for name
					{
						i = st.IndexOf("= m.n");	// no name in file, no problem
						if (i > 0)
						{
							name = st.Substring(0, i).Trim(' ');	// get name from file just before "= m.n"
							MultiID.Delete(ref st, 0, i+1);
							oK = true;
						}
					}
					if (!oK)
					{
						int iL = st.Length;
						for (i = 1; i <= iL; i++)			//Look for start of number
						{
							ch = Char.ToUpper(st[i-1]);
							if (ch >= '0' && ch <= maxD[0] &&
												(ch <= '9' || ch >= 'A'))	// get value
							{
								oK = true;
								break; // exit for
							}
						}
					}
					if (oK)
					{
					if (baseIL == 0) baseIL = 10;
					if (baseIL == 10)
					{
						ReadFNm10(inF, out oK, zI, ref fName, st);	// read in base 10
					}
					else
					{
						baseIS = MultiID.baseI;
						MultiID.baseI = baseIL;
						if (!Common.quiet) MultiID.Write("Base " + MultiID.baseI + " ");
						ReadFNmB(inF, out oK, zI, ref fName, st);	// read in base baseI from file
						MultiID.baseI = baseIS;
					}
						fini = true;
						break; // exit for
					}
				}
				while (!fini);
				if (!oK) MultiID.WriteLn(" No named number found");
			}
			catch (Exception ex)
			{
				// trap read error
				MultiID.WriteLn(" Read error file \"" + fName + '"');
				Common.WCurDir(fName);
				Common.ReportError("ReadFNm", ex.Message);
				oK = false;
			}
		} // ReadFNm

		public static bool ReadFile(string fName, int xI)
		// read in a number from a file after opening it
		{
			StreamReader inF;	// file number to read from
			bool oK;
			string name;
			int tI;
			int t2I;
			string dir;
			if (fName == "") fName = "NoName.XPN";
			if (!Common.OpenRead(out inF, fName, out dir)) return false;
			if (!Common.quiet) MultiID.WriteLn("Reading number file \"" + fName + "\" ");
			if (xI != 0)
			{
				ReadFNm(inF, out name, out oK, xI, ref fName);	// I Primitive op code
			}
			else
			{
				Common.InitNAdd(1, "ReadFile-tI", out tI);
				ReadFNm(inF, out name, out oK, tI, ref fName);	// readN Procedure
				if (oK)
				{
					if (name != "")
					{
						Common.LFindAdd(name, out t2I);
						SetToII(tI, t2I);
					}
					else
					{
						SetToII(tI, Common.iTop);
					}
				}
				Common.LDelete(tI);
			}
			inF.Close();
			if (!Common.quiet)
			{
				if (name != "" && oK) MultiID.Write("containing " + name);
				MultiID.WriteLn();
				MultiID.WriteLn("File \"" + fName + "\" closed");
			}
			return true;
		} // ReadFile

		public static void CalRead(string fName, int xI)
		// determine name and read in a number from a file
		{
			if (fName == "" && xPNIn != 0)
				fName = Common.nList[xPNIn].Nm.Substring(7);		// remove "XPNIn: "
			if (fName == "" && Common.comI != 0)
				fName = Common.nList[Common.comI].Nm.Substring(6);	// remove "File: "
			if (fName == "") fName = "NoName.XPN";
			Common.FixFName(ref fName, "XPN");
			Common.CalReadN(fName, xI);
		}

		public static void CalWriteN(string fName, int xI)
		// output a number on the list to a file with name fName
		{
			StreamWriter outF; // text file output for Number
			string nm = Common.nList[xI].Nm;
			if (fName == "") fName = "NoName.XPN";
			if (!Common.ChkWrite(out outF, fName, " with " + nm)) return;	// open file, exit if not opened
			XPCalLst.FormatN(outF, nm, Common.nList[xI]); // output x to file #outF
			outF.Close();													// close the file
			// output status to the screen
			if (!Common.quiet) MultiID.WriteLn("File \"" + fName + "\" closed");
		}

		public static void CalWrite(string fName, int xI)
		// output a number on the list to a file after checking its name
		{
			if (fName == "" && xPNOut != 0)
				fName = Common.nList[xPNOut].Nm.Substring(8);		// remove "XPNOut: "
			if (fName == "" && Common.comI != 0)
				fName = Common.nList[Common.comI].Nm.Substring(6);	// remove "File: "
			if (fName == "") fName = "NoName.XPN";
			Common.FixFName(ref fName, "XPN");
			CalWriteN(fName, xI);
		}

		public static void CalLFile(ref string fName) // establish log file name
		{
			if (fName == "" && xPLOut != 0)
				fName = Common.nList[xPLOut].Nm.Substring(8);		// remove "XPLOut: "
			if (fName == "" && Common.comI != 0)
				fName = Common.nList[Common.comI].Nm.Substring(6);	// remove "File: "
			if (fName == "") fName = "NoName.XPL";
			Common.FixFName(ref fName, "XPL");
		}

		public static void CalReadConfig() // read and execute file Config.XPC
		{
			CalReadCode("Config.XPC");
		}

		public static void CalWriteConfig() // write file Config.XPC
		{
			StreamWriter outF; // text file: configuration output
			string st;
			int fMBI;
			string savDir = Environment.CurrentDirectory.ToString();
			Directory.SetCurrentDirectory(Common.homeDir);
			if (Common.ChkWrite(out outF, "Config.XPC", ""))
			{
				MultiID.WriteLn(null, outF, "@Echo Off");
				MultiID.WriteLn(null, outF, "Rem  Start of file Config.XPC");
				MultiID.WriteLn(null, outF, "BaseI(0)");
				MultiID.WriteLn(null, outF, "SetMax(" + MultiID.mMax * MultiID.muDMax + ")");
				MultiID.Write(null, outF, "LastTop=;  ");
				MultiID.Write(null, outF, fMC * MultiID.muDMax + " M;  ");
				MultiID.Write(null, outF, MultiFD.fTn * MultiID.muDMax + " T;  ");
				MultiID.Write(null, outF, MultiID.muDpG + " G;  ");
				if (MultiFD.fRound == 0) { st = "V;  "; } else { st = "U;  "; }
				MultiID.Write(null, outF, st);
				if (degMode) { st = "D"; } else { st = "E"; }
				MultiID.WriteLn(null, outF, st);
				MultiID.WriteLn(null, outF, "SetC(" + Common.mComs + ")");
				MultiID.WriteLn(null, outF, "SetD(" + MultiID.maxDis + ")");
				if (Common.saveTop) { st = "1"; } else { st = "0"; };
				MultiID.WriteLn(null, outF, "SaveTop(" + st + ")");
				if (MultiID.allowFHT) { st = "1"; } else { st = "0"; };
				MultiID.WriteLn(null, outF, "AllowFHT(" + st + ")");
				if (MultiID.forceFHT) { st = "1"; } else { st = "0"; };
				MultiID.WriteLn(null, outF, "ForceFHT(" + st + ")");
				if (MultiID.diagOn) { st = "1"; } else { st = "0"; };
				if (MultiID.debug) st = "-1";
				MultiID.WriteLn(null, outF, "Diag(" + st + ")");
				if (MultiID.timeIt && !MultiID.diagOn)
					MultiID.WriteLn(null, outF, "Time");
				if (Common.autoD) { st = "1"; } else { st = "0";};
				MultiID.WriteLn(null, outF, "AutoDisplay(" + st + ")");
				MultiID.WriteLn(null, outF, "ChDir(\"" + savDir + "\")");
				if (MultiFD.scieN) { st = "1"; } else { st = "0"; }
				MultiID.WriteLn(null, outF, "ScientificN(" + st + ")");
				Common.LFind("FMB", out fMBI);
				if (fMBI != 0)
				{
					CalWriteN("FMB.XPN", fMBI);
					MultiID.WriteLn(null, outF, "ReadN(\"FMB.XPN\")");
				}
				if (xPCIn != 0)
				{
					st = Common.nList[xPCIn].Nm.Substring(7);	// remove "XPCIn: "
					MultiID.WriteLn(null, outF, "XPCIn(\"" + st + "\")");
				}
				if (xPLOut != 0)
				{
					st = Common.nList[xPLOut].Nm.Substring(8);	// remove "XPLOut: "
					MultiID.WriteLn(null, outF, "XPLOut(\"" + st + "\")");
				}
				if (xPNIn != 0)
				{
					st = Common.nList[xPNIn].Nm.Substring(7);	// remove "XPNIn: "
					MultiID.WriteLn(null, outF, "XPNIn(\"" + st + "\")");
				}
				if (xPNOut != 0)
				{
					st = Common.nList[xPNOut].Nm.Substring(8);	// remove "XPNOut: "
					MultiID.WriteLn(null, outF, "XPNOut(\"" + st + "\")");
				}
				if (Common.comI != 0)
				{
					st = Common.nList[Common.comI].Nm.Substring(6);	// remove "File: "
					MultiID.WriteLn(null, outF, "\"" + st + "\"");
				}
				if (Common.lrnL != 0)
				{
					st = Common.nList[Common.lrnL].Nm.Substring(5); // remove "Lrn: "
					MultiID.WriteLn(null, outF, "X " + st);
				}
				if (MultiID.logg) { st = "1"; } else { st = "0"; }
				MultiID.WriteLn(null, outF, "LogScreen(" + st + ")");
				MultiID.WriteLn(null, outF, "BaseO(" + MultiID.baseO + ")");
				MultiID.WriteLn(null, outF, "BaseI(" + MultiID.baseI + ")");
				st = Common.nList[Common.iTop].Nm.ToUpper();
				if (st != "CAT" && st != "EE" && st != "EULERC" && st != "LN10" && st != "PHI" &&
					st != "PHIP" && st != "PI" && st != "UBIQ")
					MultiID.WriteLn(null, outF, Common.nList[Common.iTop].Nm + "=");
				else
					MultiID.WriteLn(null, outF, "X=");
				if (Common.quiet) { st = "1"; } else { st = "0"; }
				MultiID.WriteLn(null, outF, "Quiet(" + st + ")");
				MultiID.WriteLn(null, outF, "Pri(" + Common.pri + ")");
				MultiID.WriteLn(null, outF, "Rem  End of file Config.XPC");
				if (Common.echoB) { st = "On"; } else { st = "Off"; }
				MultiID.WriteLn(null, outF, "Echo " + st);
				outF.Close();
				if (!Common.quiet) MultiID.WriteLn("File Config.XPC closed");
			}
			Directory.SetCurrentDirectory(savDir);
		} // CalWriteConfig

		public static bool AProcedure(ref string st, ref int resSav, ref string fName) // do a procedure
		{
			int po;
			int tot;
			string stL;
			int tI;
			double db;
			string name = Common.GetField(ref st);
			int i = name.Length;
			resSav = 0;
			fName = "";
			if (i == 0 || MultiID.muErr) return false;
			if (st.Length > i)
			{
				if (st[i] == '=') return false; // if name= assignment
				if (name == "PI" && st[i] == '(') return false; // if Pi(X) function
				if (name == "PHI" && st[i] == '(') return false; // if Phi(X) function
			}
			if (name != "ALLD" &&
				name != "ALLOWFHT" &&
				name != "AUTODISPLAY" &&
				name != "BASE" &&
				name != "BASEI" &&
				name != "BASEO" &&
				name != "BERNM" &&
				name != "CAT" &&
				name != "CHDIR" &&
				name != "CLEARBERN" &&
				name != "CLEAREULER" &&
				name != "CLEARHIST" &&
				name != "CLEARLOG" &&
				name != "DIAG" &&
				name != "ECHOSCREEN" &&	// same as LogScreen
				name != "EE" &&
				name != "EULERC" &&
				name != "EULERM" &&
				name != "EXIT" &&
				name != "FORCEFHT" &&
				name != "GENBERN" &&
				name != "GENEULER" &&
				name != "HELPH" &&
				name != "HELPW" &&
				name != "HISTH" &&
				name != "HISTW" &&
				name != "LN10" &&
				name != "LOGSCREEN" &&
				name != "LT" &&
				name != "LX" &&
				name != "NEXT" &&		// "PAUSE" is in batch processing
				name != "PFA" &&
				name != "PFB" &&
				name != "PFE" &&
				name != "PHI" &&
				name != "PHIP" &&
				name != "PI" &&
				name != "PIAA" &&
				name != "PIAB" &&
				name != "PIAGM" &&
				name != "PICH" &&
				name != "PIGL" &&
				name != "PTAB" &&
				name != "PRI" &&
				name != "QUIET" &&
				name != "RAN" &&
				name != "READN" &&
				name != "RESTORE" &&
				name != "RUN" &&
				name != "RUNH" &&
				name != "RUNW" &&
				name != "SAVE" &&
				name != "SAVETOP" &&
				name != "SCIEN" &&
				name != "SCIENTIFICN" &&
				name != "SETC" &&
				name != "SETD" &&
				name != "SETM" &&
				name != "SETMAX" &&
				name != "TIME" &&
				name != "UBIQ" &&
				name != "WRITE" &&
				name != "WRITELN" &&
				name != "WRITEN" &&
				name != "XPCIN" &&
				name != "XPLOUT" &&
				name != "XPNIN" &&
				name != "XPNOUT")
			{
				return false;
			}
			Common.DelNPBls(ref st, i);		// if name never uses ()
			if (name == "BERNM" || name == "CAT" || name == "CLEARBERN" ||
				name == "CLEAREULER" || name == "CLEARHIST" || name == "CLEARLOG" ||
				name == "EE" || name == "EULERC" || name == "EULERM" ||
				name == "EXIT" || name == "LN10" || name == "LT" ||
				name == "LX" || name == "NEXT" || name == "PHI" ||
				name == "PHIP" || name == "PI" || name == "PIAA" ||
				name == "PIAB" || name == "PIAGM" || name == "PICH" ||
				name == "PIGL" || name == "RAN" || name == "RESTORE" ||
				name == "SAVE" || name == "TIME" || name == "UBIQ")
			{
				if (st != "" && st[0] == '(') // allow use of ( or () but not (x)
				{
					Common.DelNPBls(ref st, 1);
					if (st != "" && st[0] == ')') Common.DelNPBls(ref st, 1);
				}
			}
			if (name == "BERNM")	// return x = index of max Bernoulli number in storage
			{
				MultiFD.SetTo1F(2 * Common.nBern, Common.nList[Common.iTop]);
				NormN(Common.iTop);
				return true;
			}
			if (name == "CAT")	// Compute x = Catalan's constant G = 0.9159655942...
			{
				int zI;
				Cat(out zI);
				if (zI != Common.iTop)
					SetToN(Common.nList[zI], Common.iTop);
				return true;
			}
			if (name == "CLEARBERN")
			{
				Common.nBern = -1; // force message output
				Common.ClearBern();
				return true;
			}
			if (name == "CLEAREULER")
			{
				Common.nEuler = -1; // force message output
				Common.ClearEuler();
				return true;
			}
			if (name == "CLEARHIST")
			{
				Common.ClearHist();
				return true;
			}
			if (name == "CLEARLOG")
			{
				Common.ClearLog();
				return true;
			}
			if (name == "EE")	// Compute x = e = 2.71828,18284,59045...
			{
				int zI;
				Ee(out zI);
				if (zI != Common.iTop)
					SetToN(Common.nList[zI], Common.iTop);
				return true;
			}
			if (name == "EULERC")	// Compute x = Euler's constant gamma = 0.57721566490153286...
			{
				int zI;
				EulerC(out zI);
				if (zI != Common.iTop)
					SetToN(Common.nList[zI], Common.iTop);
				return true;
			}
			if (name == "EULERM")	// return x = index of max Euler number in storage
			{
				MultiFD.SetTo1F(2 * Common.nEuler, Common.nList[Common.iTop]);
				NormN(Common.iTop);
				return true;
			}
			if (name == "EXIT")	// totally quit and exit the program
			{
				MultiID.muAbort = true;
				Common.tQuitReq = true;
				Common.tExitFlag = true;
				return true;
			}
			if (name == "LN10")	// Compute x = ln(10) = 2.30258509...
			{
				int zI;
				Ln10(out zI);
				if (zI != Common.iTop)
					SetToN(Common.nList[zI], Common.iTop);
				return true;
			}
			if (name == "LX" || name == "LT")
			{
				Common.LFindAdd("LastTop", out Common.lastTop);
				SetToII(Common.lastTop, Common.iTop);
				return true;
			}
			if (name == "NEXT")
			{
				Common.iTop--;
				if (Common.iTop < 1) Common.iTop = Common.cList;
				return true;
			}
			if (name == "PHI")	// Compute x = Phi = (1 + sqrt(5)) / 2
			{
				int zI;
				Phi(out zI);
				if (zI != Common.iTop)
					SetToN(Common.nList[zI], Common.iTop);
				return true;
			}
			if (name == "PHIP")	// Compute x = PhiP = (1 - sqrt(5)) / 2
			{
				int zI;
				PhiP(out zI);
				if (zI != Common.iTop)
					SetToN(Common.nList[zI], Common.iTop);
				return true;
			}
			if (name == "PI")	// Compute x = Pi = 3.14159,2653...
			{
				int zI;
				Pi(out zI);
				if (zI != Common.iTop)
					SetToN(Common.nList[zI], Common.iTop);
				return true;
			}
			if (name == "PIAA")	// Compute x = Pi by Borwein algorithm a
			{
				SetToN(MultiFD.fZero, Common.iTop);
				MultiPi.PiAa(Common.nList[Common.iTop]);
				return true;
			}
			if (name == "PIAB")	// Compute x = Pi by Borwein algorithm b
			{
				SetToN(MultiFD.fZero, Common.iTop);
				MultiPi.PiAb(Common.nList[Common.iTop]);
				return true;
			}
			if (name == "PIAGM")	// Compute x = Pi by AGM algorithm
			{
				SetToN(MultiFD.fZero, Common.iTop);
				MultiPi.PiAGM(Common.nList[Common.iTop], true); // AGM with speedup
				return true;
			}
			if (name == "PICH")	// Compute x = Pi by Chudnovsky brothers' binary splitting algorithm
			{
				SetToN(MultiFD.fZero, Common.iTop);
				MultiPi.PiCh(Common.nList[Common.iTop]);
				return true;
			}
			if (name == "PIGL")	// Compute x = Pi by Gauss-Legendre algorithm
			{
				SetToN(MultiFD.fZero, Common.iTop);
				MultiPi.PiGL(Common.nList[Common.iTop], true); // with speedup
				return true;
			}
			if (name == "RAN")
			{
				XPCalLst.Ran();
				return true;
			}
			if (name == "RESTORE")
			{
				resSav = 1;
				return true;
			}
			if (name == "SAVE")
			{
				resSav = 2;
				return true;
			}
			if (name == "UBIQ")	// Compute x = the ubiquitous constant U = 0.84721308479...
			{
				int zI;
				Ubiq(out zI);
				if (zI != Common.iTop)
					SetToN(Common.nList[zI], Common.iTop);
				return true;
			}
			if (name == "CHDIR" || name == "READN" || name == "RUN" ||
				 name == "WRITEN" || name == "XPCIN" || name == "XPLOUT" ||
				 name == "XPNIN" || name == "XPNOUT")
			{
				tI = 0;
				if (st != "" && st[0] == '(')
				{
					Common.DelNPBls(ref st, 1);
					if (st != "" && st[0] == ')')
						Common.DelNPBls(ref st, 1);
					else if (st != "" && st[0] != '\"')
					{
						if (name == "CHDIR")
							Common.ReportSin("Directory name expected: " + name + "(|", ref st);
						else
							Common.ReportSin("File name expected: " + name + "(|", ref st);
						return true;
					}
					else
					{
						if (name == "CHDIR") Common.ChangeDir(ref st);
						if (name == "XPCIN") XPCalLst.CalFileNm("XPCIn", ref st, ref xPCIn);
						if (name == "XPLOUT") XPCalLst.CalFileNm("XPLOut", ref st, ref xPLOut);
						if (name == "XPNIN") XPCalLst.CalFileNm("XPNIn", ref st, ref xPNIn);
						if (name == "XPNOUT") XPCalLst.CalFileNm("XPNOut", ref st, ref xPNOut);
						if (name == "READN") CalRead(Common.FileNm(ref st), tI); // tI is nil
						if (name == "WRITEN") CalWrite(Common.FileNm(ref st), Common.iTop);
						if (name == "RUN")
						{
							fName = Common.FileNm(ref st);
							resSav = 3;
						}
						Common.DelNPBls(ref st, 1);
						if (st != "" && st[0] == ')') Common.DelNPBls(ref st, 1);
						return true;
					}
				}
				if (Common.comI == 0) stL = "\"";
				else stL = "\"" + Common.nList[Common.comI].Nm.Substring(5) + "\"";
				if (name == "CHDIR") Common.ChangeDir(ref stL);
				if (name == "XPCIN") XPCalLst.CalFileNm("XPCIn", ref stL, ref xPCIn);
				if (name == "XPLOUT") XPCalLst.CalFileNm("XPLOut", ref stL, ref xPLOut);
				if (name == "XPNIN") XPCalLst.CalFileNm("XPNIn", ref stL, ref xPNIn);
				if (name == "XPNOUT") XPCalLst.CalFileNm("XPNOut", ref stL, ref xPNOut);
				if (name == "READN") CalRead(Common.FileNm(ref stL), tI);
				if (name == "WRITEN") CalWrite(Common.FileNm(ref stL), Common.iTop);
				if (name == "RUN")
				{
					fName = Common.FileNm(ref stL);
					resSav = 3;
				}
				return true;
			}
			if (name != "WRITE" && name != "WRITELN")
			{
				if (st == "" || st[0] != '(')
				{
					if (name == "DIAG")
					{
						if (!MultiID.timeIt) Common.DoubleSpace();
						MultiID.debug = false;
						MultiID.diagOn = true;
						MultiID.timeIt = true;
					}
					else if (name == "TIME")
					{
						if (!MultiID.timeIt) Common.DoubleSpace();
						MultiID.debug = false;
						MultiID.diagOn = false;
						MultiID.timeIt = true;
					}
					else if (name == "PRI")
						Common.DisplayPriority(); // display priority status
					else if (name == "QUIET")
						Common.quiet = true;
					else if (name == "SCIEN")
						MultiFD.scieN = true;
					else
						Common.ReportSin("( expected: " + name + "|", ref st);
					return true;
				}
				else
				{
					Common.DelNPBls(ref st, 1);
					Common.InitNAdd(1, "AProcedure-tI-1", out tI);
					tIAP = tI;
					if (!Expression(ref st, tI))
					{
						Common.LDelete(tI);
						Common.ReportSin("Expression expected: " + name + "(|", ref st);
						return true;
					}
					if (st != "" && st[0] == ')') Common.DelNPBls(ref st, 1);
					if (MultiID.muErr)
					{
						Common.LDelete(tI);
						return true;
					}
					if (name == "ALLD")
					{
						XPCalLst.RIntSIN(tI);
						PrimeFA.PrimeAllD(tI);
					}
					else if (name == "ALLOWFHT")
					{
						MultiID.allowFHT = !Common.ZTestN(tI);
						if (!MultiID.allowFHT) MultiID.forceFHT = false;
					}
					else if (name == "AUTODISPLAY")
						Common.autoD = !Common.ZTestN(tI);
					else if (name == "BASE")
					{
						CalSBaseI(tI);
						CalSBaseO(tI);
					}
					else if (name == "BASEI")
						CalSBaseI(tI);
					else if (name == "BASEO")
						CalSBaseO(tI);
					else if (name == "DIAG")
					{
						if (!Common.ZTestN(tI) && !MultiID.timeIt) Common.DoubleSpace();
						MultiID.diagOn = !Common.ZTestN(tI);
						MultiID.debug = Common.nList[tI].S;
						MultiID.timeIt = MultiID.diagOn;
					}
					else if (name == "FORCEFHT")
					{
						MultiID.forceFHT = !Common.ZTestN(tI);
						if (MultiID.forceFHT) MultiID.allowFHT = true;
					}
					else if (name == "GENBERN")
						GenBern(tI);
					else if (name == "GENEULER")
						GenEuler(tI);
					else if (name == "HELPH")
					{
						MultiFD.GetDbInF(out db, 100, 5000, Common.nList[tI]);
						Global.objRunForm.SetHelpHeight((int)db);
					}
					else if (name == "HELPW")
					{
						MultiFD.GetDbInF(out db, 100, 5000, Common.nList[tI]);
						Global.objRunForm.SetHelpWidth((int)db);
					}
					else if (name == "HISTH")
					{
						MultiFD.GetDbInF(out db, 100, 5000, Common.nList[tI]);
						Global.objRunForm.SetHistHeight((int)db);
					}
					else if (name == "HISTW")
					{
						MultiFD.GetDbInF(out db, 100, 5000, Common.nList[tI]);
						Global.objRunForm.SetHistWidth((int)db);
					}
					else if (name == "LOGSCREEN" || name == "ECHOSCREEN")
					{
						if (MultiID.logg == Common.ZTestN(tI)) Common.ToggleLogg();
					}
					else if (name == "PFA")
					{
						XPCalLst.RIntSIN(tI);
						PrimeFA.PrimeFAA(tI);
					}
					else if (name == "PFB")
					{
						XPCalLst.RIntSIN(tI);
						XICommon.PrimeFAB(tI);
					}
					else if (name == "PFE")
					{
						XPCalLst.RIntSIN(tI);
						PrimeFA.PrimeFAE(tI);
					}
					else if (name == "PTAB")
					{
						XPCalLst.RIntSIN(tI);
						MultiID.GetDbInSI(out db, 2, Int32.MaxValue, Common.nList[tI]);
						XICommon.GenPrimeTable((int)db);
					}
					else if (name == "PRI")
					{
						MultiFD.GetDbInF(out db, -3, 3, Common.nList[tI]); // 0 for normal priority
						Common.SetPriority((int)db);
						Common.DisplayPriority();
					}
					else if (name == "QUIET")
						Common.quiet = !Common.ZTestN(tI);
					else if (name == "RUNH")
					{
						MultiFD.GetDbInF(out db, 100, 5000, Common.nList[tI]);
						Global.objRunForm.SetRunHeight((int)db);
					}
					else if (name == "RUNW")
					{
						MultiFD.GetDbInF(out db, 100, 5000, Common.nList[tI]);
						Global.objRunForm.SetRunWidth((int)db);
					}
					else if (name == "SAVETOP")
						Common.saveTop = !Common.ZTestN(tI);
					else if (name == "SCIEN" || name == "SCIENTIFICN")
						MultiFD.scieN = !Common.ZTestN(tI);
					else if (name == "SETC")
					{
						MultiFD.GetDbInF(out db, 0, 100000, Common.nList[tI]); // 0 for no change status
						Common.ReSizeHist((int)db);
					}
					else if (name == "SETD")
					{
						MultiFD.GetDbInF(out db, 2, MultiID.muNMax * MultiID.muDMax, Common.nList[tI]);
						MultiID.maxDis = (int)db;
					}
					else if (name == "SETM")
						CalSMan(tI);
					else if (name == "SETMAX")
					{
						MultiFD.GetDbInF(out db, 0, MultiID.muNMax * MultiID.muDMax, Common.nList[tI]);
						db = 1 + (db - 1) / MultiID.muDMax;
						MultiID.mMax = (int)db;
						XPCalLst.CheckNMax();
					}
					tI = tIAP;	// SetM(X) can change tI
					tIAP = 0;	// see CalDel(int zI)
					Common.LDelete(tI);
					return true;
				}
			}
			if (st != "" && st[0] == '(') // process Write and WriteLn
			{
				Common.DelNPBls(ref st, 1);
				if (st != "")
				{
					tot = 0;
					if (st != "" && st[0] == ')')
						Common.DelNPBls(ref st, 1);
					else if (st != "" && st[0] == '\"')
					{
						po = st.IndexOf("\"", 1);
						if (po < 0) po = st.Length;
						MultiID.WriteT(st.Substring(1, po - 1), ref tot);
						Common.DelNPBls(ref st, po+1);	// 1 too many ok for DelNPBls
					}
					else
					{
						Common.InitNAdd(1, "AProcedure-tI-2", out tI);
						if (!Expression(ref st, tI))
						{
							Common.LDelete(tI);
							Common.ReportSin("Expression expected: " + name + "(|", ref st);
							return true;
						}
						MultiFD.WriteF(Common.nList[tI], ref tot);
						Common.LDelete(tI);
					}
					if (st != "" && st[0] == ')') Common.DelNPBls(ref st, 1);
				}
			}
			if (name == "WRITELN") MultiID.WriteLn();
			return true;
		} // AProcedure

		public static bool AssignmentOp(string op) // is this an assignment?
		{
			return (op == "+=" || op == "-=" || op == "*=" || op == "/=" || op == "%=");
		}

		public static bool Assignment(ref string st, ref int zI)
		// do an assignment, zI unchanged if not an assignment
		{
			int pI; // pointer to left member of assignment statement
			int tI;
			string name = Common.GetField(ref st);
			int iL = name.Length;
			if (iL == 0 || iL == st.Length) return false;
			if (st.Length > iL+2)
			{
				string op = st.Substring(iL, 2);
				if (AssignmentOp(op))
				{
					op = op[0] + "(";
					st = name + "=" + name + op + st.Substring(iL+2);
				}
			}
			if (st[iL] == '=')
			{
				if (Variable(ref st, out pI))	// pI points to new top, may be the same as old top
				{
					Common.DelNPBls(ref st, 1);			// delete the = sign
					zI = pI;
					if (st.Length == 0)
					{
						return true;					// merely change top
					}
					Common.InitNAdd(1, "Assignment-tI", out tI);
					if (Expression(ref st, tI))
					{
						SetToII(tI, zI);
						Common.LDelete(tI);
						return true;
					}
					Common.LDelete(tI);
				}
			}
			return false;
		} // Assignment

		public static void ListReport() // report the contents of the nList
		// output name and value for each item on the list
		{
			int tot;
			int uB = Common.cList;
			int cI = uB;
			MultiID.WriteDLn(Common.StringOf(40, "-"));
			while (cI >= 1)
			{
				tot = 0;
				MultiID.WriteT(cI + ": ", ref tot);
				Common.WriteNV(Common.nList[cI], ref tot);
				if (MultiID.diagOn)
					MultiID.WriteT(" N=" + Common.nList[cI].N + " M=" +
						Common.nList[cI].M + " U=" + Common.nList[cI].V.GetUpperBound(0), ref tot);
				MultiID.WriteLn();
				if (cI > 1) MultiID.WriteLn(); // double space between values
				cI--;
			}
			MultiID.WriteLn(Common.StringOf(40, "-"));
		}

		public static void CalReadCode(string fName) // read in a Cal code file and Run it
		{
			if (fName == "" && xPCIn != 0)
				fName = Common.nList[xPCIn].Nm.Substring(7);		// remove "XPCIn: "
			if (fName == "" && Common.comI != 0)
				fName = Common.nList[Common.comI].Nm.Substring(6);	// remove "File: "
			if (fName == "") fName = "NoName.XPC";
			Common.FixFName(ref fName, "XPC");
			if (!Common.RunFile(fName))
			{
				if (Common.MakeReady() == DialogResult.OK)			// pause for operator to make file/drive ready
				{
					if (!Common.RunFile(fName))
						MultiID.WriteLn("Aborting file input...");
				}
				MultiID.WriteLn();
			}
		}

		public static void CalDel(int zI) // delete zI from list
		// don't ever delete x at zI = 1, careful, zI and iTop may be the same Integer
		{
			if (zI > 1)
			{
				if (zI == Common.comI) Common.comI = 0;
				if (zI == Common.lrnL) Common.lrnL = 0;
				if (zI == xPCIn) xPCIn = 0;
				if (zI == xPLOut) xPLOut = 0;
				if (zI == xPNIn) xPNIn = 0;
				if (zI == xPNOut) xPNOut = 0;
				if (zI == tIAP) tIAP = 0;
				Common.LDelete(zI);
				if (Common.comI > zI) Common.comI--;
				if (Common.lrnL > zI) Common.lrnL--;
				if (xPCIn > zI) xPCIn--;
				if (xPLOut > zI) xPLOut--;
				if (xPNIn > zI) xPNIn--;
				if (xPNOut > zI) xPNOut--;
				if (tIAP > zI) tIAP--;
				if (Common.iTop >= zI) Common.iTop--;
			}
			else
			{
				if (Common.iTop == 1) Common.iTop = Common.cList;
			}
		}

		public static void CalComment(ref string st) // get Comment from command line in st
		{
			XPCalLst.CalFileNm("File", ref st, ref Common.comI);
		}

		public static void CalSDpG(int zI)
		// set digits per group in number output display [0, nMax * muDMax], 0 => no ,'s
		{
			double db;
			MultiFD.GetDbInF(out db, 0, Common.nMax * MultiID.muDMax, Common.nList[zI]);
			MultiID.muDpG = (int)db;
		}

		public static void CalSBaseO(int zI)
		// set Display base in input and output [2, 36], 0 => 10, 'A' = 10, 'Z' = 35
		{
			double db;
			string maxD; // max Input digit "1" to "Z"
			MultiFD.GetDbInF(out db, 0, 36, Common.nList[zI]);
			if (db < 2) db = 10;
			MultiID.baseO = (int)db;
			maxD = MultiID.MaxDig(MultiID.baseO);
			if (!Common.quiet) MultiID.WriteDLn("BaseO = " + MultiID.baseO + " base ten, Max digit = " + maxD);
		}

		public static void CalSBaseI(int zI)
		// set Display base in input and output [2, 36], 0 => 10, 'A' = 10, 'Z' = 35
		{
			double db;
			string maxD; // max Input digit "1" to "Z"
			MultiFD.GetDbInF(out db, 0, 36, Common.nList[zI]);
			if (db < 2) db = 10;
			MultiID.baseI = (int)db;
			maxD = MultiID.MaxDig(MultiID.baseI);
			if (!Common.quiet) MultiID.WriteDLn("BaseI = " + MultiID.baseI + " base ten, Max digit = " + maxD);
		}

		public static void SetFMB() // set Modulo base FMB in MultiID package to FMB on the Common.nList
		{
			int fMBI;
			int n;
			int m;
			Common.LFindAdd("FMB", out fMBI);
			n = Common.nList[fMBI].N;
			m = MultiID.fMB.M;
			if (m != n)
			{
				MultiID.fMB.M = n;
				try
				{
					MultiID.fMB.V = new int[n+1];	// re-dimention value array
				}
				catch (Exception ex)
				{
					long totalMemory = GC.GetTotalMemory(false);
					string st = ex.Message + ", M = " + n + ", FMB set to zero, Memory used = " + totalMemory;
					Common.ReportError("SetFMB", st);
					MultiID.DoneSI(MultiID.fMB);
					return;
				}
			}
			MultiID.SetToSI(Common.nList[fMBI], MultiID.fMB);
		}

		public static void CalExxLrn(int zI) // setup to execute learned line x times
		{
			double db;
			MultiFD.GetDbInF(out db, 0, Int32.MaxValue, Common.nList[zI]);
			Common.exX = (int)db;
		}

		public static bool Primitive(ref string st, int zI) // do operation
		{
			if (MultiID.muErr) return false;
			string op = st.Substring(0, 1).ToUpper();	// operation code character "+", "S", etc.
			if (op == " " || op == ";")					// " " and ";" never get this far
			{} // no-op
			else if (op == "A")
				Common.autoD = !Common.autoD;
			else if (op == "B")
				Common.CalDLrn(ref st);
			else if (op == "C")
			{
				Common.nList[zI].S = !Common.nList[zI].S;
				MultiID.NormSI(Common.nList[zI]);
			}
			else if (op == "D")
				degMode = true;
			else if (op == "E")
				degMode = false;
			else if (op == "F" || op == "!")
				XPCalLst.RFacN(zI);
			else if (op == "#")
			{
				XPCalLst.RIntSIN(zI);
				XICommon.Primorial(zI);
				NormN(zI);
			}
			else if (op == "G")
				CalSDpG(zI);
			else if (op == "H")
				Common.ToggleLogg();
			else if (op == "I")
				CalRead("", Common.iTop);
			else if (op == "J")
				CalReadCode("");
			else if (op == "K")
				CalExxLrn(zI);
			else if (op == "L")
				XPCalLst.RLopN(zI);
			else if (op == "M")
				CalSMan(zI);
			else if (op == "N")
				RanN(zI);
			else if (op == "O")
				XPCalLst.RInvN(zI);
			else if (op == "P")
			{
				int pI;
				Pi(out pI);
				SetToII(pI, zI);
			}
			else if (op == "Q")
			{
				MultiID.muAbort = true;
				Common.tQuitReq = true;
			}
			else if (op == "R")
				XPCalLst.RSqRtN(zI);
			else if (op == "S")
				XPCalLst.RSqN(zI);
			else if (op == "T")
				XPCalLst.CalSFTn(zI);
			else if (op == "U")
				MultiFD.fRound = MultiID.baseM / 2;
			else if (op == "V")
				MultiFD.fRound = 0;
			else if (op == "W")
				CalWrite("", Common.iTop);
			else if (op == "X")
				Common.CalExLrn(ref st);
			else if (op == "Y")
				CalDel(zI);
			else if (op == "Z")
				ListReport();
			else if (op == "\"")
				CalComment(ref st);
			else if (op == "%")
				XPCalLst.SetFMBN(zI);
			else if (op == "/")
				XPCalLst.RModFMBN(zI);
			else if (op == @"\")
			{
				CalSBaseI(zI);
				CalSBaseO(zI);
			}
			else if (op == "$")
			{
				RunForm.ClearOutput();
				new Calc();				// re-initialize class Calc
			}
			else if (op == ">")
				CalWriteConfig();
			else if (op == "<")
			{
				st = "";
				CalReadConfig();
			}
			else if (op == "]")
				Common.SaveHist();
			else if (op == "[")
				Common.RestoreHist();
			else if (op == ".")
			{
				int tot = 0;
				MultiFD.WriteFixedL(MultiID.outS, null, Common.nList[Common.iTop],ref tot, 0);
			}
			else if (op == "?")
				RunForm.HelpForm();
			else
			{
				return false;
			}
			Common.DelNPBls(ref st, 1);
			return true;
		} // Primitive

		public static void GenBern(int zI)
		// generate even numbered Bernoulli numbers B(0) thru B(zI) = bernN[i/2] / bernD[i/2]
		{
			double db;
			MultiFD.GetDbInF(out db, 4, Common.maxBern + 1, Common.nList[zI]);
			int n = (int)db;
			if (n > Common.maxBern)
				Common.ReportError("GenBern", "n > " + Common.maxBern + ", too large for Bernoulli number");
			else
				Common.GenBernI(n);
			MultiID.muErr = false; // because no value is returned to nList[nI]
		}

		public static void GenEuler(int zI)
		// generate even numbered Euler numbers E(0) thru E(zI) = euler[i/2]
		{
			double db;
			MultiID.GetDbInSI(out db, 4, Common.maxEuler + 1, Common.nList[zI]);
			int n = (int)db;
			if (n > Common.maxEuler) // n too large
					Common.ReportError("GenEuler", "n > " + Common.maxEuler + ", too large for Euler number");
			else
				Common.GenEulerI(n);
			MultiID.muErr = false; // because no value is returned to nList[nI]
		}

		public static void EulerG(MultiF nF, int zI)
		// z = E(x), the generalized Euler number of x
		{
			if (!nF.S && nF.C >= 0) // if x >= 0 and x is an integer, use Euler(n)
			{
				Euler(nF, zI);
				return;
			}
			bool saveExp = MultiFD.expanded;
			int saveFMC = fMC;
			int saveMMax = MultiID.mMax;
			XPCalLst.Expand();
			int tI;
			Common.InitNAdd(1, "EulerG-tI", out tI); // E(n) = 2 * Beta(-n)
			MultiF bN = new MultiF(nF.N);
			MultiFD.SetToF(nF, bN);
			MultiFD.ChSF(bN);	// bN = -n
			XPCalLst.BetaNF(bN, tI);
			MultiFD.RMulF(MultiFD.fTwo, Common.nList[tI]); // * 2
			SetToN(Common.nList[tI], zI);
			Common.LDelete(tI);
			MultiFD.expanded = saveExp;
			fMC = saveFMC;
			MultiID.mMax = saveMMax;
			NormN(zI);
		} // EulerG

		public static void BernG(MultiF nF, int zI)
		// z = B(x), the generalized Bernoulli number of x
		{
			if (!nF.S && nF.C >= 0)	// if x >= 0 and x is an integer, use Bern(n)
			{
				if (nF == MultiFD.fOne)
					SetToN(MultiFD.fHalf, zI);
				else
					Bern(nF, zI);
				return;
			}
			bool saveExp = MultiFD.expanded;
			int saveFMC = fMC;
			int saveMMax = MultiID.mMax;
			XPCalLst.Expand();
			int tI;
			Common.InitNAdd(1, "BernG-tI", out tI); // B(n) = -n * Zeta(1-n)
			MultiF bN = new MultiF(fMC);
			MultiFD.SetToF(nF, bN);
			MultiFD.ChSF(bN);
			MultiFD.RAddF(MultiFD.fOne, bN); // bN = 1-n
			XPCalLst.ZetaNF(bN, tI);
			MultiFD.ChSF(Common.nList[tI]);
			MultiFD.RMulF(nF, Common.nList[tI]); // * -n
			SetToN(Common.nList[tI], zI);
			Common.LDelete(tI);
			MultiFD.expanded = saveExp;
			fMC = saveFMC;
			MultiID.mMax = saveMMax;
			NormN(zI);
		} // BernG

		public static void Bern(MultiF nF, int zI)
		// z = B(n), the n'th Bernoulli number
		{
			int tot = 0;
			if (MultiID.debug)
			{
				MultiID.WriteT("Bern: n = ", ref tot);
				MultiFD.WriteFLn(nF, ref tot);
			}
			if (nF.S) { ClearN(zI); return; } // n negative
			MultiF nL = new MultiF(4);
			MultiFD.IntF(nF, nL);
			if (nL.C == 0 && (nL.V[0] & 1) != 0)	// odd n > 0
			{
				if (nL.N == 1 && nL.V[0] == 1)
				{
					SetToN(MultiFD.fMHalf, zI);
					return;
				}
				ClearN(zI);
				return;
			}
			MultiF lim = new MultiF(4);
			int j;
			MultiFD.ValueF10("4.05997,83000,01705,888E+18", out j, lim);
			if (nL > lim)
			{
				MultiID.MuWriteErr("Number too large for Bernoulli number");
				ClearN(zI);
				return;
			}
			MultiF bN = new MultiF(4);
			MultiF bD = new MultiF();
			bool saveExp = MultiFD.expanded;
			int saveFMC = fMC;
			int saveMMax = MultiID.mMax;
			XPCalLst.Expand();
			MultiF limBernF = new MultiF(1);
			limBernF &= limBern;
			lim &= 2 * Common.nBern;
			if (nL > lim && nL > limBernF)
			{
				bool aGo = true;
				if (!MultiFD.ZTestF(bernPrev) && nL >= bernPrev)
				{
					MultiID.MuWriteErr("Bern: In a tight loop computing Bernoulli numbers");
					ClearN(zI);
					aGo = false;
				}
				if (aGo)
				{
					MultiFD.SetToF(nL, bernPrev);
					int tI;
					Common.InitNAdd(1, "Bern-tI", out tI); // B(n) = -n * Zeta(1-n)
					bN &= 1;
					nL.S = true; // -n
					MultiFD.RAddF(nL, bN); // bN = 1-n
					XPCalLst.ZetaNF(bN, tI);
					MultiFD.RMulF(nL, Common.nList[tI]); // * -n
					SetToN(Common.nList[tI], zI);
					Common.LDelete(tI);
					// ends up as B(n) = -(-1)^(n/2) * n * 2 * gamma(n) * Zeta(n) / (2*Pi)^n
					// and Zeta(n) = eta(n) / (1 - 2^(1-n))
					// and Zeta(1-n) = eta(1-n) / (1 - 2^(n))
					// and eta(1-n) = [ (-1)^(n/2) * gamma(n) * eta(n) / (2*Pi)^n ] * [ (1 - 2^n) / (0.5 - (1/2^n)) ]
				}
				MultiFD.ClearF(bernPrev);
			}
			else
			{
				XPCalLst.BernN(nF, bN);
				if (MultiID.muErr || MultiID.muAbort)
					bD &= 1;
				else
					XPCalLst.BernD(nF, bD);
				XPCalLst.DivN(bN, bD, zI);
			}
			MultiFD.expanded = saveExp;
			fMC = saveFMC;
			MultiID.mMax = saveMMax;
			NormN(zI);
		} // Bern

		public static void Euler(MultiF nF, int zI)
		// z = E(n), the n'th Euler number
		{
			int tot = 0;
			if (MultiID.debug)
			{
				MultiID.WriteT("Euler: n = ", ref tot);
				MultiFD.WriteFLn(nF, ref tot);
			}
			if (nF.S) { ClearN(zI); return; } // n negative
			MultiF nL = new MultiF(4);
			MultiFD.IntF(nF, nL);
			if (nL.C == 0 && (nL.V[0] & 1) != 0)	// odd n > 0
			{
				ClearN(zI);
				return;
			}
			MultiF lim = new MultiF(4);
			int j;
			MultiFD.ValueF10("4.05997,83000,01705,888E+18", out j, lim);
			if (nL > lim)
			{
				MultiID.MuWriteErr("Number too large for Euler number");
				ClearN(zI);
				return;
			}
			MultiF eN = new MultiF(4);
			bool saveExp = MultiFD.expanded;
			int saveFMC = fMC;
			int saveMMax = MultiID.mMax;
			XPCalLst.Expand();
			MultiF limEulerF = new MultiF(1);
			limEulerF &= limEuler;
			lim &= 2 * Common.nEuler;
			if (nL > lim && nL > limEulerF)
			{
				bool aGo = true;
				if (aGo)	// E(n) = (-1)^(n/2) * 2 * gamma(n+1) * beta(n+1) / (Pi/2)^(n+1)
				{
					MultiF d = new MultiF(fMC);
					MultiF n = new MultiF(fMC);
					int tI, t2I;
					Common.InitNAdd(1, "Euler-tI", out tI);
					Common.InitNAdd(1, "Euler-t2I", out t2I);
					MultiFD.Add1F(nL, 1, eN);								// eN = n+1
					XPCalLst.BetaNF(eN, tI);								// t = beta(n+1)
					XPCalLst.GamNF(eN, t2I);								// t2 = gamma(n+1)
					MultiFD.MulF(Common.nList[tI], Common.nList[t2I], n);	// n = b * g
					MultiFD.MulF(n, MultiFD.fTwo, n);						// n = 2 * b * g
					int pI = XPCalLst.GetPiPtr();
					MultiFD.DivF(Common.nList[pI], MultiFD.fTwo, d);		// d = pi / 2
					XPCalLst.PowN(d, eN, tI);								// t = (Pi / 2) ^ (n+1)
					MultiFD.DivF(n, Common.nList[tI], d);					// d = b * g / t
					d.S = nL.C == 0 && (nL.V[0] & 3) == 2;					// sign = (n mod 4 == 2)
					SetToN(d, zI);
					Common.LDelete(tI);
					Common.LDelete(t2I);
				}
			}
			else
			{
				XPCalLst.EulerN(nF, eN);
				SetToN(eN, zI);
			}
			MultiFD.expanded = saveExp;
			fMC = saveFMC;
			MultiID.mMax = saveMMax;
			NormN(zI);
		} // Euler

		public static void Cat(out int zI)	// enter Catalan's constant G = 0.915965594177...
		{
			Common.LFind("Cat", out zI);	// search the list, if there point to it
			if (zI == 0 || Common.nList[zI].N != Calc.fMC ||
				Common.nList[zI].S)	// if not on the list or not good
			{
				Common.LFindAdd("Cat", out zI);	// add it to the list if not there and point to it
				ClearN(zI);
				XPCalLst.BetaN(MultiFD.fTwo, zI);
			}
		}

		public static void Ee(out int zI)	// enter e = Exp(1) = 2.718281828459045...
		{
			Common.LFind("Ee", out zI);		// search the list, if there point to it
			if (zI == 0 || Common.nList[zI].N != Calc.fMC ||
				Common.nList[zI].S)	// if not on the list or not good
			{
				Common.LFindAdd("Ee", out zI);	// add it to the list if not there and point to it
				ClearN(zI);
				XPCalLst.ExpN(MultiFD.fOne, zI);
			}
		}

		public static void EulerC(out int zI)	// enter Euler's constant gamma = -psi(1) = .5772156649...
		{
			Common.LFind("EulerC", out zI);		// search the list, if there point to it
			if (zI == 0 || Common.nList[zI].N != Calc.fMC ||
				Common.nList[zI].S)	// if not on the list or not good
			{
				Common.LFindAdd("EulerC", out zI);	// add it to the list if not there and point to it
				ClearN(zI);
				XPCalLst.PsiN(MultiFD.fOne, zI);
				Common.nList[zI].S = false;
			}
		}

		public static void Ln10(out int zI)	// enter the natural log of 10 = 2.30258509...
		{
			Common.LFindAdd("Ln10", out zI);	// add it to the list if not there and point to it
			XPCalLst.SetToLn10N(zI);
		}

		public static void Phi(out int zI)	// enter Phi = (1 + sqrt(5)) / 2 = 1.61803,39887...
		{
			Common.LFind("Phi", out zI);	// search the list, if there point to it
			if (zI == 0 || Common.nList[zI].N != Calc.fMC ||
				Common.nList[zI].S)	// if not on the list or not good
			{
				Common.LFindAdd("Phi", out zI);	// add it to the list if not there and point to it
				ClearN(zI);
				bool saveExp = MultiFD.expanded;
				int saveFMC = fMC;
				int saveMMax = MultiID.mMax;
				XPCalLst.Expand();
				MultiF a = new MultiF(fMC);
				MultiFD.SqRootF(MultiFD.fFive, a);
				MultiFD.RAddF(MultiFD.fOne, a);
				MultiFD.RDivF(MultiFD.fTwo, a);
				SetToN(a, zI);
				MultiFD.DoneF(a);
				MultiFD.expanded = saveExp;
				fMC = saveFMC;
				MultiID.mMax = saveMMax;
				NormN(zI);
			}
		}

		public static void PhiP(out int zI)	// enter PhiP = (1 - sqrt(5)) / 2 = -0.61803,39887...
		{
			Common.LFind("PhiP", out zI);	// search the list, if there point to it
			if (zI == 0 || Common.nList[zI].N != Calc.fMC ||
				Common.nList[zI].S)	// if not on the list or not good
			{
				Common.LFindAdd("PhiP", out zI);	// add it to the list if not there and point to it
				ClearN(zI);
				bool saveExp = MultiFD.expanded;
				int saveFMC = fMC;
				int saveMMax = MultiID.mMax;
				XPCalLst.Expand();
				MultiF a = new MultiF(fMC);
				MultiFD.SqRootF(MultiFD.fFive, a);
				a.S = true;
				MultiFD.RAddF(MultiFD.fOne, a);
				MultiFD.RDivF(MultiFD.fTwo, a);
				SetToN(a, zI);
				MultiFD.DoneF(a);
				MultiFD.expanded = saveExp;
				fMC = saveFMC;
				MultiID.mMax = saveMMax;
				NormN(zI);
			}
		}

		public static void Pi(out int zI)	// enter Pi = 3.141592653...
		{
			Common.LFindAdd("Pi", out zI);	// add it to the list if not there and point to it
			XPCalLst.SetToPiN(zI);
		}

		public static void Ubiq(out int zI) // enter the ubiquitous constant U = 0.8472130847...
		{
			Common.LFind("Ubiq", out zI);	// search the list, if there point to it
			if (zI == 0 || Common.nList[zI].N != Calc.fMC ||
				Common.nList[zI].S)	// if not on the list or not good
			{
				Common.LFindAdd("Ubiq", out zI);	// add it to the list if not there and point to it
				ClearN(zI);
				bool saveExp = MultiFD.expanded;
				int saveFMC = fMC;
				int saveMMax = MultiID.mMax;
				XPCalLst.Expand();
				MultiF a = new MultiF(fMC);
				MultiFD.SqRootF(MultiFD.fHalf, a);	// U = common mean of Sqrt(0.5) and 1
				XPCalLst.MeanCN(a, MultiFD.fOne, zI);
				MultiFD.DoneF(a);
				MultiFD.expanded = saveExp;
				fMC = saveFMC;
				MultiID.mMax = saveMMax;
				NormN(zI);
			}
		}

		public static void Cleanup() // cleanup named list after a run-time error
		{
			Common.LDelete("AFunction-t2I");
			Common.LDelete("AFunction-t3I");
			Common.LDelete("AFunction-tI");
			Common.LDelete("AProcedure-tI-1");
			Common.LDelete("AProcedure-tI-2");
			Common.LDelete("Assignment-tI");
			Common.LDelete("Bern-tI");
			Common.LDelete("Condition-tI");
			Common.LDelete("Euler-t2I");
			Common.LDelete("Euler-tI");
			Common.LDelete("Expression-tI");
			Common.LDelete("Power-t2I");
			Common.LDelete("Power-tI");
			Common.LDelete("ReadFile-tI");
			Common.LDelete("ReadFNm10-tI");
			Common.LDelete("SimpExpr-tI");
			Common.LDelete("Term-t2I");
			Common.LDelete("Term-tI");
			GC.Collect();	// force garbage collection of all generations
		} // Cleanup

		public static bool degMode;		// true if in Degree trig mode, false if radian mode
		public static double ti0;		// base time, see Sub ReportBest
		public static double ti1;		// delta time of iterations
		public static double ti2;		// delta time to evaluate series
		public static double tic;		// seconds per DOS clock tick
		public static int fMC;			// current max # of super digits in a result
		public static int limBern;		// Limit of small Bernoulli number index
		public static int limEuler;		// Limit of small Euler number index
		public static int tIAP;			// index to AProcedure temp item
		public static int xPCIn;		// code input list item, its name has the File name
		public static int xPLOut;		// log output list item, its name has the File name
		public static int xPNIn;		// number input list item, its name has the File name
		public static int xPNOut;		// number output list item, its name has the File name
		public static MultiF bernPrev;	// previous value of n in Bern to prevent a loop
		// How many Bernoulli numbers does it take to compute a Bernoulli number B(n)?
		// It better be less than B(n). Bern calls Zeta, which calls Bern
		public static string nL;		// one Environment.NewLine \n or \r or \r\n
	}
}
