// ***************** COPYRIGHT (c) 2006 STEFAN WANER ******************// *********************** ALL RIGHTS RESERVED ************************// ***  IT ALSO REMAINS TO DO THE TOPMATTER// Globalswindow.onerror = myErrorTrap;var e = 2.718281828459045;var pi = 3.141592653589793;var theColor = 0; // the color of a pixelvar numColors = 7;var theDot = new Array();var counter = 0; // for debugging	theDot[0] = new Image();	theDot[0].src = "pixelwhite.gif"	theDot[1] = new Image();	theDot[1].src = "pixelblack.gif"; 	theDot[2] = new Image();	theDot[2].src = "pixelred.gif"; 	theDot[3] = new Image();	theDot[3].src = "pixelgreen.gif";	theDot[4] = new Image();	theDot[4].src = "pixelblue.gif";	theDot[5] = new Image();	theDot[5].src = "pixelmagenta.gif";	theDot[6] = new Image();	theDot[6].src = "pixelorange.gif";	theDot[7] = new Image();	theDot[7].src = "pixelyellow.gif";	theDot[8] = new Image();	theDot[8].src = "litepixelblack.gif"; 	theDot[9] = new Image();	theDot[9].src = "litepixelred.gif"; 	theDot[10] = new Image();	theDot[10].src = "litepixelgreen.gif";	theDot[11] = new Image();	theDot[11].src = "litepixelblue.gif";	theDot[12] = new Image();	theDot[12].src = "litepixelmagenta.gif";	theDot[13] = new Image();	theDot[13].src = "litepixelorange.gif";	theDot[14] = new Image();	theDot[14].src = "litepixelyellow.gif";var X = 0;var x = 0;var y = 0;var x1 = 0;var x2 = 0;var y1 = 0;var y2 = 0;var h = 0;var xh = 0;var hx = 0;var t = 0;var th = 0;var ht = 0;var a = 0;var b = 0; // end points of graphvar c = 0;var d = 0;var A = 0;var p1 = 0;var numDivisions = 50; // for each curvevar quoteMark = unescape( '%22' );var singlequoteMark = unescape( '%27' );var numX = 200; // picure width in pixelsvar numY = 200; // picture heightvar infinity = 10000000000000  // 10^13;var windowcropTally = 20; 	// will not cut a window in half if more than this number of      // pixels pop out of range as a resultvar theCanvas = new makeArray2(numX,numY);var autoY = true;var autoGridline = true;var okToRoll = true;var theString = "";var theFunction = ""; // the functionvar xGridLines = new Array();var yGridLines = new Array();var lineColor = 2; // redvar lineColorLite = lineColor + 7;var xAxisPosition = 50; // position of axes = -1 if not visiblevar yAxisPosition = 100;var xGridStep = 10;var yGridStep = 10;var xVals = new Array(); // to store the values of x for evlauatorvar yVals = new Array();  // to store the functionsvar tminVals = new Array(); var tmaxVals = new Array();var arraysize = 0; // number of functionsvar xArraysize = 0; // number of x-values in evalautorvar maxnum = 5;  // max number of functions allowedvar maxnumX = 12; // max number of x-values allowedvar theValues = new makeArray2(maxnumX, maxnum); // copy of evalauator datavar fracMode = false; // fraction mode off defaultvar numSigDigs = 5;  // rounding of y-values defaultvar maxDenom = 99999;// *** end globals// *** Error Handler ******function myErrorTrap(message,url,linenumber) {alert("It looks like you have entered something wrongly. Press 'Show Examples' to see to to format functions.");return (true);} // end of on error// ********************// **********Utilities to read in the functions *********// ********************************************************************function setUp(){	okToRoll = true;	with(Math){				//Step 1: read the inputs into an array and decide		// how many points there are		var thexCellName = ""; // these are strings to names x1, x2,.. 		var theInstruction = ""; // a javascript instuction		var doIt = 0; // a dummy variable						//Step 2: Fill the y arrays with the functions 		for (var i = 1; i <= maxnum; i++) {			theInstruction = "yVals["+i+"] = stripSpaces(document.theFormA.y"+i+".value);"			doIt = eval(theInstruction);			} // i		// Step 3: Compute how many functions there are		for (i = 1; i <= maxnum; i++) {			if (yVals[i] == "") {				arraysize = i-1;				i = maxnum}			} // i		if (arraysize == 0) {alert("You must enter at least one function"); okToRoll = false}	} //with math} // setup// ***********************************************************************// ************** End of Reading-in Parametric Equations Utility ******// ***********************************************************************// ***********************************************************************// ************** Evaluator Setup Routine ******// ***********************************************************************function setUp2() {	okToRoll = true;	var a = setUp(); // read in the functions	fracMode = document.theFormC.fracModeButton.checked;	if(!fracMode) {		numSigDigs = document.theFormC.acc.value;		if (isBad(numSigDigs)) {alert("the Number of Significant Digits must be a number. I am setting it back to 5. Change it to another number if you like."); okToRoll = false}	} // if not fraction mode	// Now read in the x-values	with(Math){		//Step 1: read the inputs into an array and decide		// how many points there are		var thexCellName = ""; // these are strings to names x1, x2,.. 		var theInstruction = ""; // a javascript instuction		var doIt = 0; // a dummy variable						//Step 2: Fill the x array with the x-values		// Note: at this point theywill all be strings 		for (var i = 1; i <= maxnumX; i++) {			theInstruction = "xVals["+i+"] = stripSpaces(document.theFormC.x"+i+".value);"			doIt = eval(theInstruction);			} // i		// Step 3: Compute how many functions there are		for (i = 1; i <= maxnumX; i++) {			if (xVals[i] == "") {				xArraysize = i-1;				break				} // encountered blank			} // i		if (xArraysize == 0) {alert("You must enter at least one value of x"); okToRoll = false}// alert(xArraysize);	} //with Math} // end of function setUp2// ***********************************************************************// ************** End of Evaluator Setup Routine ******// ***********************************************************************// ***********************************************************************// ************** Evaluate all Routine ******// ***********************************************************************function evaluateAll() {// This evaluates all the functions in nthe table// we have arraysize many functions and xArraysize many values of x var theStrg = ""; // a dummy string for parsed functionsvar theInstruction = ""; // a javascript instuctionvar doIt = 0; // a dummy action// First clear the current y-valuesfor (var i = 1; i <= maxnum; i++) {	for (var j = 1; j <= maxnumX; j++) {		theInstruction = "document.theFormC.y"+i+"x"+j+".value = ''";		doIt = eval(theInstruction)		} // j	} // i// Now Compute the values for (var j = 1; j <= arraysize; j++) {	theStrg = myParse(yVals[j]);	for (var i = 1; i <= xArraysize; i++) {		x = myEval(xVals[i]); // in case there are inputs like "sin(3)"		y = checkEval(theStrg);		if (y > infinity) y = "infinity";		else if (y < -infinity) y = "-infinity";		if (!fracMode) theInstruction = "document.theFormC.y"+j+"x"+i+".value = roundSigDig(y,numSigDigs)";		else theInstruction = "document.theFormC.y"+j+"x"+i+".value = toFrac(y, maxDenom)";		doIt = eval(theInstruction);// alert(theInstruction);		} // end i	} // end j} // end of evaluateAll// ***********************************************************************// ************** End of Evaluate all Routine ******// ***********************************************************************// **************** Plot All Curves ********************function plotAllCurves(){var theyString = "";var thexMin = 0;var thexMax = 0;lineColor = 2; // redfor (var i = 1; i <= arraysize; i++) {		theyString = yVals[i];	thexMin = a;	thexMax = b;	var p = drawCurve(theyString, thexMin, thexMax);	lineColor +=1;	if (lineColor == 8) lineColor = 2;   // no yellow please	} // i} // end of plot// ******************End of Plot All Curves ***********function sesame(url,hsize,vsize){ // Default size is 550 x 400        var tb="toolbar=0,directories=0,status=0,menubar=0"        tb+=",scrollbars=1,resizable=1,"    var tbend="width="+hsize+",height="+vsize;    if(tbend.indexOf("<undefined>")!=-1){tbend="width=550,height=400"}        tb+=tbend        Win_1 = window.open("","win1",tb);        Win_1 = window.open(url,"win1",tb);	Win_1.focus();    }function stripSpaces (InString)  {	OutString=""; 	if (InString == "") return (OutString);	for (Count=0; Count < InString.length; Count++)  {		TempChar=InString.substring (Count, Count+1);		if (TempChar!=" ")			OutString=OutString+TempChar;	}	return (OutString);}function stripChar (InString,symbol)  {	OutString="";	for (Count=0; Count < InString.length; Count++)  {		TempChar=InString.substring (Count, Count+1);		if (TempChar!=symbol)			OutString=OutString+TempChar;	}	return (OutString);}function replaceChar (InString,oldSymbol,newSymbol)  {	OutString="";	for (Count=0; Count < InString.length; Count++)  {		TempChar=InString.substring (Count, Count+1);		if (TempChar!=oldSymbol)			OutString=OutString+TempChar		else OutString=OutString+newSymbol;	}	return (OutString);}function makeArray2 (X,Y)	{	var count;	this.length = X+1;	for (var count = 1; count <= X+1; count++)		// to allow starting at 1		this[count] = new makeArray(Y);	} // makeArray2function makeArray (Y)	{	var count;	this.length = Y+1;	for (var count = 1; count <= Y+1; count++)		this[count] = 0;	} // makeArrayfunction rightString (InString, num)  {	OutString=InString.substring (InString.length-num, InString.length);	return (OutString);}function rightTrim (InString)  {	var length = InString.length;	OutString=InString.substring(0,length-1);	return (OutString);}function checkString(InString,subString,backtrack)// check for subString// if backtrack = false, returns -1 if not found, and left-most location in string if found// if backtrack = true, returns -1 if not found, and right-most location in string if found// note that location is to the left of the substring in both cases{var found = -1;var theString = InString;var Length = theString.length;var symbLength = subString.length;for (var i = Length- symbLength; i >-1; i--)	{		TempChar=theString.substring (i, i+ symbLength);	if (TempChar == subString) 			{			found = i;			if (backtrack) i = -1			}	} // ireturn(found);} // checkfunction replaceSubstring (InString,oldSubstring,newSubstring)  {	OutString="";	var sublength = oldSubstring.length;	for (Count=0; Count < InString.length; Count++)  {		TempStr=InString.substring (Count, Count+sublength);		TempChar=InString.substring (Count, Count+1);		if (TempStr!= oldSubstring)			OutString=OutString+TempChar		else 			{			OutString=OutString+ newSubstring;			Count +=sublength-1			}	}	return (OutString);} function parser (InString, Sep)  {	NumSeps=1;	for (Count=1; Count < InString.length; Count++)  {		if (InString.charAt(Count)==Sep)			NumSeps++;	}	parse = new makeArray (NumSeps+4, "");		// my adjustments	Start=0; Count=1; ParseMark=0;	LoopCtrl=1;	while (LoopCtrl==1)  {		ParseMark = InString.indexOf(Sep, ParseMark);		TestMark=ParseMark+0;		if ((TestMark==0) || (TestMark==-1)){			parse[Count]= InString.substring (Start, InString.length);			LoopCtrl=0;			break;		}		parse[Count] = InString.substring (Start, ParseMark);		Start=ParseMark+1;		ParseMark=Start;		Count++;	}	parse[0]=Count;	return (parse);}function winopen(){// opens a window in the bottom frame	var str = winopen.arguments[0];	var loc = winopen.arguments[1];	if (navigator.appName == "Microsoft Internet Explorer") this.parent.bottom.window.location = str;	else window.open(str,loc);} // winopenfunction looksLikeANumber(theString) {// returns true if theString looks like it can be evaluatedvar result = true;var length = theString.length;var x = ""var y = "1234567890-+/*. "var yLength = y.length;for (var i = 0; i <= length; i++)	{ 	x = theString.charAt(i);		result = false;		for (var j = 0; j <= yLength; j++) 			{			if (x == y.charAt(j)) {result = true; break}			} // j	if (result == false) return(false);	} // ireturn(result);} // looks like a numberfunction shiftRight(theNumber, k) {	if (k == 0) return (theNumber)	else		{		var k2 = 1;		var num = k;		if (num < 0) num = -num;		for (var i = 1; i <= num; i++)			{			k2 = k2*10			}		}	if (k>0) 		{return(k2*theNumber)}	else 		{return(theNumber/k2)}	}function roundSigDig(theNumber, numDigits) {	with (Math)		{		if (isBad(theNumber)) return theNumber;		if (theNumber == 0) return(0);		else if(abs(theNumber) < 0.000000000001) return(0);// WARNING: ignores numbers less than 10^(-12)		else			{			var k = floor(log(abs(theNumber))/log(10))-numDigits+1			var k2 = shiftRight(round(shiftRight(abs(theNumber),-k)),k)			if (theNumber > 0) return(k2);			else return(-k2)			} // end else		}} // roundSigDigfunction roundDec(theNumber, numPlaces) {with (Math)	{	var x =shiftRight(round(shiftRight(theNumber,numPlaces)),-numPlaces);	return x;	} // with math} // roundDec// ********* FUNCTION PARSER ***********function myEval(theString){if (isBad(x)) return x;return(eval(myParse(theString)));	}function checkEval(theString){if (isBad(x)) return x;return(eval(theString));}// The above function requires all the following routinesfunction breakApart(InString) {	// ******* Input: any string such as aaa*bbb or (aa*aa)*bbb	// *** This Routine Retuns two pieces	// *** bbb starts at the left-most operation *, /,  - or +	// *** if it sees a paren, it stops after closure.	theString = InString;	var Length = theString.length;	var outArray = new Array();	outArray[1] = theString;	outArray[2] = "";	var parenCount = 0;	var parenWatch = false;	var looking = true;			if (theString.substring (0,1) == "(")		{		parenCount++;		parenWatch = true;		looking = false;		}	// Look for operators		for (Count=1; Count < Length; Count++)  		{		TempChar=theString.substring (Count, Count+1);		if (TempChar == "(") 			{parenCount ++;}		else if (TempChar == ")") {parenCount = parenCount-1};		if ((parenCount == 0) && (parenWatch == true))			 {			parenWatch = false;			outArray[1] = theString.substring (0, Count+1);			outArray[2] = theString.substring (Count+1, Length);			}		if (looking == true)			{		if ( ( (TempChar == "*") || (TempChar == "/") || (TempChar == "-")  ) || ( (TempChar == "+") || (TempChar == ')' )  )  )				{ 									{					// alert(Count);					looking = false;					outArray[1] = theString.substring (0, Count);					outArray[2] = theString.substring (Count, Length);					// alert (outArray[1]);					// alert(outArray[2]);					} // end if hit one				} 			} // end if looking		} // end of loop	return (outArray);} // end of breakApartfunction isNumberChar (InString)  {	if(InString.length!=1) 		return (false);	RefString="1234567890)";	if (RefString.indexOf (InString, 0)==-1) 		return (false);	return (true);}function isCharHere (InString, RefString)  {	if(InString.length!=1) 		return (false);	if (RefString.indexOf (InString, 0)==-1) 		return (false);	return (true);}function putProduct(InString) {OutString="";for (Count=0; Count < InString.length; Count++)  {		TempChar=InString.substring (Count, Count+1);		if (!isCharHere(TempChar,"xXeslcapdDuUhHtT(") || (Count == 0) )			{OutString=OutString+TempChar}		else 			{			if (isNumberChar(InString.substring(Count-1,Count)))				{OutString=OutString+"*"+TempChar}			else OutString=OutString+TempChar			}	}	return (OutString);}function reverse (InString)  {	OutString="";	var Length = InString.length;	for (Count=Length; Count > -1; Count--)  {		TempChar=InString.substring (Count, Count+1);		if (TempChar == "(") {TempChar = ")"}		else if  (TempChar == ")") {TempChar = "("}		OutString=OutString+TempChar;		}	return (OutString);	}function powFix2(InString) {	// ****Replaces one "^" by "pow"	theString = InString;	var Length = theString.length;	outString = theString; 		// in case nothing happens			// Look for wedge	var looking = true;	for (Count=0; Count < Length; Count++)  		{		if (looking)			{			TempChar=theString.substring (Count, Count+1);			if (TempChar == "^")				{				looking = false;				rightStr = theString.substring (Count+1,Length);				leftStr = theString.substring (0,Count);				// deal with right-hand string				Aray = breakApart(rightStr);				Arg2 = Aray[1];				rightRest = Aray[2];							backString = reverse(leftStr);				Aray = breakApart(backString);				Arg1 = reverse(Aray[1]);				leftRest = reverse(Aray[2]);				outString = leftRest+"Math.pow("+Arg1+","+Arg2+")"+rightRest;								} // end hif hit a wedge			} // end of looking for a wedge		} // end of loop// ****** testing *******// document.Extra.diagnostics.value += outString + cr;// ***** end testing *****return (outString);} // end of powFix2function powCheck(InString) {	// ****checks for ^		theString = InString;	var Length = theString.length;		// Look for wedge	var found = false;	for (Count=0; Count < Length; Count++)  		{		TempChar=theString.substring (Count, Count+1);		if (TempChar == "^")			{			found = true;			} // end if hit a wedge		} // end of looking for a wedge	return(found);} // end of powCheckfunction isBad(x) {if((isNaN(x)) || (x > infinity) || (x < -infinity)) return(true);else return(false)}function myParse(expression){		var theString = stripSpaces(expression);				with (Math)			{		// now convert formatting from GC formatting				theString = putProduct(theString);		theString = replaceSubstring(theString,"log","(1/Math.log(10))*Math.log");		theString = replaceSubstring(theString,"ln","Math.log");		theString = replaceSubstring(theString,"abs","Math.abs");			while (powCheck(theString))				{				theString = powFix2(theString);				// alert(theString);				}		theString = theString.toLowerCase();		theString = replaceSubstring (theString,"math.","Math."); 		// in case the user put in a math. something// alert(theString);			} // with Math		theString = replaceSubstring (theString,"exp","Math.exp");		theString = replaceSubstring (theString,"cos","Math.cos");		theString = replaceSubstring (theString,"sin","Math.sin");		theString = replaceSubstring (theString,")(",")*(");		theString = replaceSubstring (theString,")ln",")*ln");		theString = replaceSubstring (theString,"sqrt","Math.sqrt");		return(theString);} // myParse// ******** END FUNCTION PARSER **************function toFrac(x, maxDenom) {	if (isBad(x)) return x;	var theFrac = new Array();	theFrac[1] = 0;	theFrac[2] = 0;	var p1 = 1;	var p2 = 0;	var q1 = 0;		var q2 = 1;		var u =0;	var t = 0;	var flag = true;	var negflag = false;	var a = 0;	var xIn = x; // variable for later	var n = 0;	var d = 0;	var p = 0;	var q = 0;	if (x >10000000000) return(theFrac);while (flag)	{	if (x<0) {x = -x; negflag = true; p1 = -p1}	var intPart = Math.floor(x);	var decimalPart = roundSigDig((x - intPart),15);	x = decimalPart;	a = intPart;		t = a*p1 + p2;	u = a*q1 + q2;	if  ( (Math.abs(t) > 10000000000 ) || (u > maxDenom ) ) 		{			n = p1;			d = q1;			break;		}		p = t;		q = u;			//		cout << "cf coeff: " << a << endl; // for debugging//		cout << p << "/" << q << endl;	// for debugging			if ( x == 0 )		{		n = p;		d = q;		break;		}		p2 = p1;		p1 = p;		q2 = q1;		q1 = q;		x = 1/x;		} // while ( true );		theFrac[1] = n;	theFrac[2] = d;	if (theFrac[2] == 1) return (theFrac[1].toString());	else return (theFrac[1] + "/" + theFrac[2]);} // toFrac// ***********************************************// **** Graphing Routine// ***********************************************function readBasics() {// alert("here");var theStrg = "";  // dummy string for evaluating functionsautoY = document.theFormB.autoYButton.checked;autoGridline = document.theFormB.autoGridButton.checked;// get the graph window information	for (var k = 1; k <= 1; k++)	{	var aa = document.theFormB.a.value; 	if (aa == "") { alert("You have not entered a number for xMin."); okToRoll = false; break;}	a = myEval(aa);	if (isNaN(a) ) { alert("You have not entered a number for xMin."); okToRoll = false; break;}	var bb = document.theFormB.b.value; 	if (bb == "") { alert("You have not entered a number for xMax."); okToRoll = false; break}	b = myEval(bb); 	if (isNaN(b) ) { alert("You have not entered a number for xMax."); okToRoll = false; break;}	if ( (okToRoll) && (a >= b)) { alert("xMax should be larger than xMin"); okToRoll = false; break;}	if(!autoY) {// alert("Here autoY is off");		var cc = document.theFormB.c.value; 		if (cc == "") { alert("You have not entered a number for yMin. (Otherwise click on 'Auto'.)"); okToRoll = false; break}		c = myEval(cc); 		if (isNaN(c) ) { alert("You have not entered a number for yMin. (Otherwise click on 'Auto'.)"); okToRoll = false; break;}		var dd = document.theFormB.d.value; 		if (dd == "") { alert("You have not entered a number for yMax. (Otherwise click on 'Auto'.)"); okToRoll = false; break}		d = myEval(dd); 		if (isNaN(d) ) { alert("You have not entered a number for yMax. (Otherwise click on 'Auto'.)"); okToRoll = false; break;}		if ( (okToRoll) && (c >= d)) { alert("yMax should be larger than yMin"); okToRoll = false; break;}		} // end of if autoY	else {		document.theFormB.c.value = ''; // cannnot have it both ways		document.theFormB.d.value = ''; 		// Must compute ymin and ymax here		var deltax = (b-a)/numX;		var maxy = 0;		var miny = 0;		var firstCheck = true;		for (var j = 1; j <= arraysize; j++) {			theStrg = myParse(yVals[j]);			for (var i = 0; i <= numX; i++)				{				x = a + i*deltax;// alert("x = " + x);				y  = checkEval(theStrg);				if (!isNaN(y) &&( y < infinity) && (y > -infinity))					{					// alert ("y = " + y);					if (firstCheck) 						{						firstCheck = false; 						maxy = y; 						miny = y						}					if (y > maxy) maxy = y;					else if (y < miny) miny = y;					} // end of if y is a legit number				} // i			} // j	// alert("miny = "+miny + "maxy =" + maxy);			// Now cut down the size of the window if necessary			// in the case of graphs shooting off to infinity			// the tequnique is to eliminate "outliers" by cropping 			// the window.// *** Why don't we just compute the st deviation and crop to +- 3s			var cutting_down = true;			var invisible_tally = 0;			while (cutting_down)				{				maxy = maxy/2;				miny = miny/2;				invisible_tally = 0;				for (var j = 1; j <= arraysize; j++) {					theStrg = myParse(yVals[j]);					for (var i = 0; i <= numX; i++)						{						x = a + i*deltax;						y  = checkEval(theStrg);						if (!isNaN(y) &&( y < infinity) && (y > -infinity))							{							if ((y > maxy) || (y < miny))								{								invisible_tally++;								if (invisible_tally > windowcropTally)									{									cutting_down = false;									maxy = 2*maxy;									miny = 2*miny;									i = numX;									break;									} // too many invisible;								} // if y > ymax						} // if is a number					} // i				} // j			} // while cutting_down// alert("miny = "+miny + "maxy =" + maxy);				if (miny == maxy) {miny  = miny-1; maxy += 1}		var scalefactor = 150/(maxy - miny); // ************// end of y min and ymax window coords// ************		c = eval(roundSigDig(miny,4)); // sets the globals		d = eval(roundSigDig(maxy,4));		} // end of else for autoY// alert("c = " + c + " d = " + d);// At this point we have the globals a, b, c, d we need	if(!autoGridline) {		var xk = document.theFormB.xg.value;		if (xk == "") xGridStep = 0;		else xGridStep = eval(xk);		var yk = document.theFormB.yg.value;		if (yk == "") yGridStep = 0;		else yGridStep = eval(yk);		} // end of if not autoGridline	else {		document.theFormB.xg.value = ''; 		document.theFormB.yg.value = ''; // cannnot have it both ways.		var pq = Math.round((b-a)/8);		if (pq == 0) pq = (b-a)/8;		xGridStep = pq;		pq = Math.round((d-c)/8);		if (pq == 0) pq = (d-c)/8;		yGridStep = pq;		} // end of else for autoGridline	} // end of single loop (k)}// ********************************************************************// *********** Initilaize the Canvas & Draw the Axes and Gridlines ****// ********************************************************************function makeGraph(){// first initialize the canvasfor (var i = 1; i <= numX; i++) for (var j = 1; j <= numY; j++) theCanvas[i][j] = 0;// first read and parse the function	readBasics();if (okToRoll)	{// alert("a = "+a+"b="+b+"c="+c+"d = "+d);	// now draw the axes & gridlines	// gridlines first	// setup position of gridlines	if (xGridStep > 0) xGridLines[0] = Math.floor(  (b-a)/xGridStep );	else xGridLines[0] = 0;	if (yGridStep > 0) yGridLines[0] = Math.floor(  (d-c)/yGridStep );	else yGridLines[0] = 0;	// initialize these arrays to zero 	for (var i = 1; i <= xGridLines[0]; i++) xGridLines[i] = 0;	for (var i = 1; i <= yGridLines[0]; i++) yGridLines[i] = 0;	var pq = 0; // just a dummy variable	if (a*b >= 0) {		for (var i = 1; i <= xGridLines[0]; i++)			{			xGridLines[i] = Math.round( i*xGridStep*numX/(b-a)  ) // alert("i = " + i + " : " + xGridLines[i] + cr);			} // x Grid Line Positions		} // if a and b have the same sign	else 		{ // want the y-axis to be one of the gridlines		for (var i = 1; i <= xGridLines[0]; i++)			{			pq = Math.round((i*xGridStep - a)*numX/(b-a));			if ((pq <= numX) && (pq >= 0)) xGridLines[i] = pq;			else break;			} // loop i		for (var j = 1; j <= xGridLines[0] - i; j++)			{			pq = Math.round((-j*xGridStep - a)*numX/(b-a));// alert("j = " + j + "pq = " + pq);			if ((pq <= numX) && (pq >= 0)) xGridLines[j+i] = pq;			else xGridLines[j+i] = 0;			} // loop j		} // a and b have opposite sign	if (c*d >= 0) {		for (var i = 1; i <= yGridLines[0]; i++)			{			yGridLines[i] = Math.round( i*yGridStep*numY/(d-c)  )			} // y Grid Line Positions		} // if c and d have the same sign	else {		for (var i = 1; i <= yGridLines[0]; i++)			{			pq = Math.round((i*yGridStep - c)*numY/(d-c));			if ((pq <= numY) && (pq >= 0)) yGridLines[i] = numY - pq;			else break;			} // loop i		for (var j = 1; j <= yGridLines[0] - i; j++)			{			pq = Math.round((-j*yGridStep - c)*numY/(d-c));// alert("j = " + j + "pq = " + pq);			if ((pq <= numY) && (pq >= 0)) yGridLines[j+i] = numY - pq;			else yGridLines[j+i] = 0;			} // loop j		} // if c and d have oppositve sign	for (var i = 1; i <= xGridLines[0]; i++) 		{// alert("i = " + i + " : " + xGridLines[i] + "of " + xGridLines[0]);		var p = xGridLines[i];		if (p > 0) {			for (var k = 1; k <= numY; k++) if (theCanvas[p][k] != lineColor) theCanvas[p][k] = 7;			} // if p is positive		} // i// alert("here");	for (var i = 1; i <= yGridLines[0]; i++) 		{		var p = yGridLines[i];		if (p > 0) {			for (var k = 1; k <= numX; k++) if (theCanvas[k][p] != lineColor) theCanvas[k][p] = 7;			} // IF P IS POSITIVE		} // i	// now the axes	if ((a < 0) && (b > 0)) yAxisPosition = Math.round((-a)*numX/(b-a));else yAxisPosition = -1;	if ((c < 0) && (d > 0)) xAxisPosition = Math.round(d*numY/(d-c));else xAxisPosition = -1;	if (yAxisPosition > 0) for (var k = 1; k <= numY; k++) theCanvas[yAxisPosition][k] = 1;	if (xAxisPosition > 0) for (var k = 1; k <= numX; k++) theCanvas[k][xAxisPosition] = 1;// alert("here");} // oktoRoll	} // makeGraph// ******************** End Initialize Graph*****************// ************** DISPLAY GRAPH *************function displayTheGraph()  {// puts up the graph in the appropriate window, and extra things as needed	// *** Open a window	var tb="toolbar=0,directories=0,status=0,menubar=0"	tb+=",scrollbars=1,resizable=1,"	var tbend="width=350,height=300"	tb+=tbend	Win_1 = window.open("","win1",tb);	Win_1.document.open();	// ** Window is openedvar theString  = '<html><title>Your Graph</title><body bgcolor = "FFFFFF"><p><center><table><tr>'theString += '<td></td><td align = center>' + roundDec(d,4) + '</td></tr><tr><td valign = center>'+ roundDec(a,4)+'</td><td>';theString += '<table border = 1><tr><td>';theString += formatGraph2();			// the actual graphtheString += '</td></tr></table>';theString += '</td><td valign = center>' + roundDec(b,4) + '</td></tr><tr><td><td align = center>' + roundDec(c,4) + '</td></tr></table></center></body></html>';Win_1.document.write(theString);Win_1.document.close();Win_1.focus();} // displayTheGraph// ********** END DISPLAY GRAPH *************// ************** FORMAT GRAPH *************// Requires the following global variables:// 1. theCanvas = the matrix of pixels -- entries are the colors 0-numCols// 2. numX, numY, the dimensions of the canvas// 3. theDot: an array of pixel images (gif) -- little swaths of color// Returns the html for the actual graphfunction formatGraph2() {var theString = "";var repeats = new Array(); // this contains a list of different rows in theCanvasvar theRow1 = new makeArray(numY);repeats[1] = 1; // first rowvar numRepeats = 1; var oldVal = 0;var newVal = 0;var theLength = 0;var theHeight = 0;for (var k = 1; k <= numY; k++) theRow1[k] = theCanvas[k][1];for (var i = 1; i <= numY; i++)	{// if (i == 100) alert('Here i = ' + i);	for (var j = i+1; j <= numY; j++)		{// if (j == 100) alert('Here j = ' + j);		for (var k = 1; k <= numX; k++)			{// if (k == 100) alert('Here k = ' + k);			if (theRow1[k] != theCanvas[k][j])				{				numRepeats++;				repeats[numRepeats] = j;				for (var p = 1; p <= numY; p++) theRow1[p] = theCanvas[p][j]; 				i = j-1;				k = numX;				j = numY;				} // if			} // k		} // j	} // irepeats[numRepeats+1] = numY+1; // for last line height// var theTestString = '';// for (var i = 1; i <= numRepeats; i++) theTestString += "," + repeats[i];// document.theForm.output.value += theTestString;// alert("here. numRepeats = " + numRepeats );var theRow = 1;for (var i = 1; i <= numRepeats; i++)	{ 	theLength = 1;	theRow = repeats[i];	theHeight = repeats[i+1] - repeats[i];	oldVal = theCanvas[1][theRow];	for (var j = 2; j <= numX; j++)		{		 if ((j == numX)  && ( theCanvas[j][theRow] != oldVal) )			{			var LL = theLength-1;			theString += '<img src = "' + theDot[oldVal].src + '" width = ' + LL + ' height = ' + theHeight + '>'			theString += '<img src = "' + theDot[theCanvas[j][theRow]].src + '" width = 1 height = ' + theHeight + '>'						} // change on last pixel		else if(( theCanvas[j][theRow] != oldVal) || (j == numX))			{			// saw a change// alert(i);// alert(j);			// make a string of the right length			theString += '<img src = "' + theDot[oldVal].src + '" width = ' + theLength + ' height = ' + theHeight + '>'			oldVal = theCanvas[j][theRow];			theLength = 0;			} 		theLength++;		} // j	theString += '<br>';	} // ireturn(theString);} // formatGraph// ********** END FORMAT GRAPH *************// ************** SEGMENT *************function clippedSegment(x1,y1,x2,y2, shadingDown){// draws a segment on the global palette// requires global window coords: xMax, yMax, xMin, yMin// shadingDown = 0 for no shading 1 for shading down -1 for shading up// if no shading check whether inside the window at all// don't bother to plot it in this case.if ((shadingDown == 0) && ((x1 >= b) || (x2 <= a))) return(0);else if ((shadingDown == 0) && ((y1 >= d) & (y2 >= d))) return(0);else 	{	// in range	var xMin = a;	var xMax = b;	var yMin = c;	var yMax = d; // counter++;// if (counter == 5) alert("xMin = "+ xMin + "xMax = "+ xMax + "yMin = "+ yMin + " yMax = "+ yMax);	var x1bar = Math.round( numX*(x1-xMin)/(xMax-xMin) );	var x2bar = Math.round( numX*(x2-xMin)/(xMax-xMin) );	var y1bar = Math.round( numY*(yMax-y1)/(yMax-yMin) );	var y2bar = Math.round( numY*(yMax-y2)/(yMax-yMin) );// Now draw the actual segment in the right color	var deltaX = x2bar - x1bar;	var deltaY = y2bar - y1bar; // alert(x2bar);// alert(y2bar);// alert(deltaX);// alert(deltaY);	var shading = true; // avoid shading same vertical line twice	var xx = 0;	var y = 0;	var xadj = 0; // anti-aliasing neighbors	var yadj = 0;	var xold = 0;	var yold = 0;	var xint = 0;	var yint = 0;	var numSteps = 0;	var theYStep = 0; 	var theXStep = 0;	var theColor = 0;	// latter are actual steps on the screen 	var xOK = false;	var yOK = false;	if ( Math.abs(deltaX) > Math.abs(deltaY) ) {numSteps = Math.abs(deltaX); xOK = true}	else {numSteps = Math.abs(deltaY); yOK = true}// alert(numSteps);	theXStep = deltaX/numSteps;	theYStep = deltaY/numSteps// set initial pixelxx = x1bar; y = y1bar; // alert("xx = " + xx + "y = " + y);// if (x1 == 0) alert(xx);if (( xx >= 1) && (y >= 1)  && (xx <= numX) && (y <= numY)) {theCanvas[xx][y] = lineColor} // alert(shadingDown);// now do the shading under or above the initial pixel// note that up is actually down in the canvas (like scren coordinates)if (shadingDown == -1)	{	if ((xx >= 1) && (xx <= numX))		{		theColor = 2; // not feasible		if (yint >= yMax) for (var k = 1; k <= numY; k++) 			{			if(theCanvas[xx][k] != lineColor) theCanvas[xx][k] = theColor;			}		else if  (( yint >= yMin) &&  (yint <= yMax)) for (var k = 1; k < yint; k++) 			{			if(theCanvas[xx][k] != lineColor) theCanvas[xx][k] = theColor;			}		}	}else if (shadingDown == 1)// shading down	{	if ((xx >= 1) && (xx <= numX))		{		theColor = 2; // not feasible		if (yint <= 0) for (var k = 1; k <= numY; k++) 			{			if(theCanvas[xx][k] != lineColor) theCanvas[xx][k] = theColor;			}		else if  (( yint >= 1) &&  (yint <= numY)) for (var k = yint+1; k < numY; k++) 			{			if(theCanvas[xx][k] != lineColor) theCanvas[xx][k] = theColor;			}		}	}for (var i = 1; i <= numSteps; i++)	{// alert(xx);// alert(y);	xold = Math.round(xx); // to record whether x changed (for shading)	yold = Math.round(y);	xx += theXStep;  	y += theYStep;	xint = Math.round(xx);	yint = Math.round(y);	if (xint > xold) shading = true;	else shading = false;	if (( xint >= 1) && (yint >= 1)  && (xint <= numX) && (yint <= numY)) 	theCanvas[xint][yint] = lineColor;	// now do anti-aliasing	// sets adjacent pixels light if they are not already set in the	// line color	if ((xint != xold) && (yint != yold)) {		for (var k = -1; k <= 1; k++) {			for (var k2 = -1; k2 <= 1; k2++) {				xadj = xint + k; 					yadj = yint + k2;				if ((xadj >= 1) && (yadj >= 1)  && (xadj <= numX) && (yadj <= numY) &&  (theCanvas[xadj][yadj] == 0)) { theCanvas[xadj][yadj] = lineColorLite}				} // k2			} // k		} // if both x and y changed	// now do the shading	if (shading)		{		if (shadingDown == -1) 			{			if ((xint >= 1) && (xint <= numX))				{				theColor = 2; // not feasible				if (yint >= numY) for (var k = 1; k <= numY; k++) 				{				if(theCanvas[xint][k] != lineColor) theCanvas[xint][k] = theColor;				}				else if  (( yint >= 1) &&  (yint <= numY)) for (var k = 1; k < yint; k++)				{				if(theCanvas[xint][k] != lineColor) theCanvas[xint][k] = theColor;				}				}			}		else if (shadingDown == 1)		// shading down			{// if (i == 1) alert("here");			if ((xint >= 1) && (xint <= numX))				{				theColor = 2; // not feasible				if (yint <= 0) for (var k = 1; k <= numY; k++) 				{				if(theCanvas[xint][k] != lineColor) theCanvas[xint][k] = theColor;				}				else if  (( yint >= 1) &&  (yint <= numY)) for (var k = yint+1; k < numY; k++)				{				if(theCanvas[xint][k] != lineColor) theCanvas[xint][k] = theColor;				}				}			}		} // if shading	} // i	} // if in range} // segment// ********** END SEGMENT *************// **************** DRAWCURVE ******************************// *** Draws a graph of a given funtionfunction drawCurve(theyString, thexMin, thexMax) {// alert("at DrawCurve; theyString = " + theyString + " thexMin = "+ thexMin + " thexMax = "+ thexMax);// Draws curve using function clippedSegment(x1,y1,x2,y2,shadingDown) repeatedly// a and b are Xmin and Xmax respectivelyokToRoll = true;var theStrg = myParse(theyString);if (thexMax <= thexMin) {alert("Xmin must be less than Xmax. Correct this and try again."); okToRoll = false}if (okToRoll) {			// Search for a place to start the graph 			// (in case initial y-coords are undefined or infinite.) 			var deltax = (thexMax - thexMin)/numDivisions;// alert(deltax);			x1 = thexMin;			x = x1;			y1 = checkEval(theStrg);// alert("x1 = " + x1 + "y1 = "+ y1 + (y1 > infinity));			if(isBad(y1)) {// alert("**HERE**")				for (var k = thexMin; k <= thexMax; k+=deltax) {					x = k;					x1 = k;					y1 = checkEval(theStrg);					if(!isBad(y1)) break;					} // end count// alert(x1);				if (k >= thexMax) {alert("Y is not defined for your given X-range."); okToRoll = false}				if (y1 > infinity) y1 = infinity;				else if (y1 < -infinity) y1 = -infinity;				} // y1 is not a number						} // if OKtoRollif (okToRoll) {		// now plot the points// alert(x);			var thecount = 0; /// testing		var startingX = x + deltax;		for (var k = startingX; k <= thexMax; k+=deltax) {			thecount++;// if (thecount == 35) alert("thcount = " + thecount + "k = "+k);// if (thecount == 41) alert("thcount = " + thecount + "k = "+k);			x2 = k;			x = x2;			y2 = checkEval(theStrg);			if (!isBad(y2)) {				if (y2 > infinity) y2 = infinity;				else if (y2 < -infinity) y2 = -infinity; 				var p = clippedSegment(x1,y1,x2,y2,0);				x1 = x2;				y1 = y2;				} // If second point is defined			else {				for (var p = x2+deltax; p <= thexMax; p+=deltax) {					x = p;					y1 = checkEval(theStrg);					if(!isBad(y1)) break;					} // end count				k = p; // reset k further along the loop				x1 = p;  // y1 is already what it is supposed to be				} // second point was undefined							if(thecount >= numDivisions + 2) k = thexMax+1;			} // k// alert("k over");	} // if okToRoll} // function drawCurve// ************** various miscellaneous routines *************function rememberValues() {if (document.theFormC.y1x1.value != "") {	var theInstruction = ""; // a javascript instuction	var doIt = 0; // a dummy variable	for (var i = 1; i <= maxnumX; i++) {		for (var j = 0; j <= maxnum; j++) {		if (j > 0) theInstruction = " theValues[i][j] = document.theFormC.y"+j+"x"+i+".value";		else theInstruction = " theValues[i][j] = document.theFormC.x"+i+".value";		doIt = eval(theInstruction);		} // j	} // i} // IF THERE IS SOMETHING IN THE FIRST CELL} // remember valuesfunction bringBackValues() {	if (document.theFormC.y1x1.value == "") {		var theInstruction = ""; // a javascript instuction		var doIt = 0; // a dummy variable		for (var i = 1; i <= maxnumX; i++) {			for (var j = 0; j <= maxnum; j++) {			if (j > 0) theInstruction = " document.theFormC.y"+j+"x"+i+".value = theValues[i][j]";			else theInstruction = " document.theFormC.x"+i+".value = theValues[i][j]";			doIt = eval(theInstruction);			} // j		} // i	} // if there is nothing in the first cell} // remember values