// ***************** COPYRIGHT (c) 2008 STEFAN WANER ******************
// *********************** ALL RIGHTS RESERVED ************************


// strategy:
// look for 0level operators in order: exp, *, /, -, +
// this is an operator whose paren count is zero 
// eg (( ---))*(--) or --*() or sin(x)*y
// these recursed first using product, quotient rule and special rules for exponents.
// if no 0-level ope, it means we have sin(--) cos (--) , abs, exp, ln
// so feed these back in.
// I think that is all...

function deriv(arg) {

} // deriv


function stringDeriv(InString) {
// returns the first derivative 
InString = putProduct(InString);
// first remove outer parens if any
InString = removeOuterParen(stripSpaces(InString));
// alert(InString);

// alert(InString);
if (InString == "x") return ("1");
else if (isNumeric (InString, "pie")) return ("0");
else {
//alert("*" + InString + "*")
	var sumArr = breakApartAtOperation (InString, 0, "+");
// alert(sumArr);
	if (sumArr[0] == "+") {
		if (stringDeriv(sumArr[1]) == "0") return(stringDeriv(sumArr[2]));
		else if (stringDeriv(sumArr[2]) == "0") return(stringDeriv(sumArr[1]));
		return(stringDeriv(sumArr[1]) + " + " + stringDeriv(sumArr[2]));
		}

	var prodArr = breakApartAtOperation (InString, 0, "*");
	var diffArr = breakApartAtOperation (InString, 0, "-");
// alert(diffArr);
	if (diffArr[0] == "-") return(stringDeriv(diffArr[1]) + " - " + stringDeriv(diffArr[2]));
	var prodArr = breakApartAtOperation (InString, 0, "*");
	if (prodArr[0] == "*") {
		if (stringDeriv(prodArr[1]) == "0") return(postFormat(prodArr[1] + "*(" + stringDeriv(prodArr[2]) + ")") );
		else if (stringDeriv(prodArr[2]) == "0") return(postFormat(prodArr[2] + "*(" + stringDeriv(prodArr[1]) + ")" ));
		else return(postFormat("(" + stringDeriv(prodArr[1]) + ")*(" + prodArr[2] + ")+(" + prodArr[1] + ")*(" + stringDeriv(prodArr[2]) + ")" ));
		}
	var quotArr = breakApartAtOperation (InString, 0, "/");
	if (quotArr[0] == "/") {
		if (stringDeriv(quotArr[1]) == "0") return(postFormat("-" + quotArr[1] + "*(" + stringDeriv(quotArr[2]) + ")/(" + postFormat(quotArr[2]) + ")^2"));
		else if (stringDeriv(quotArr[2]) == "0") return(postFormat( "("+ removeOuterParen(stringDeriv(quotArr[1])) + ")/" + quotArr[2] ));
		else return(postFormat("((" + removeOuterParen(stringDeriv(quotArr[1])) + ")*(" + removeOuterParen(quotArr[2]) + ")-(" + removeOuterParen(quotArr[1]) + ")*(" + removeOuterParen(stringDeriv(quotArr[2])) + "))/(" + removeOuterParen(quotArr[2]) + ")^2" ));
		}	

	var powArr = breakApartAtOperation (InString, 0, "^");
	if (powArr[0] == "^") {
		if (powArr[2] == "2") return(postFormat(powArr[2] + "*"+ powArr[1] + "*("+stringDeriv(powArr[1]) + ")"   ));
		else if (isNumeric (powArr[2])) return(postFormat(powArr[2] + "*"+ powArr[1] + "^" + (parseFloat(powArr[2])-1).toString() ) + "*("+stringDeriv(powArr[1]) + ")"   );
		else {
			var theLnCoeff = stringDeriv(powArr[2]);
			if (theLnCoeff == "1") theLnCoeff = "";
			else if (theLnCoeff == "-1") theLnCoeff = "-";
			if (isNumeric (powArr[1])) return(postFormat(powArr[1] + "^" + powArr[2] + "*(" + theLnCoeff + "ln(" + powArr[1] + "))"   )  );

		else return(postFormat(powArr[1] + "^" + powArr[2] + "*(" + theLnCoeff + "ln(" + powArr[1] + ")+" + powArr[2]+"*"+stringDeriv(powArr[1]) + "/" + powArr[1] + ")"   )  )
			} // exponent is not a number
		}

	var sinPos = InString.indexOf("sin");
	if (sinPos == 0) {
		var sinArr = parseOuterParen(InString,sinPos,"(",false);
		if (isNumeric (sinArr [3])) return ("0");
		else return(postFormat("("+ postFormat(stringDeriv(sinArr[3])) + ")*cos(" + sinArr[3] + ")"  ))
		} // sine

	var cosPos = InString.indexOf("cos");
	if (cosPos == 0) {
		var cosArr = parseOuterParen(InString, cosPos,"(",false);
		if (isNumeric (cosArr [3])) return ("0");
		else return(postFormat("(-1)*("+ postFormat(stringDeriv(cosArr[3])) + ")*sin(" + cosArr[3] + ")"  ))
		} // cosine

	var tanPos = InString.indexOf("tan");
	if (tanPos == 0) {
		var tanArr = parseOuterParen(InString, tanPos,"(",false);
		if (isNumeric (tanArr [3])) return ("0");
		else return(postFormat("("+ postFormat(stringDeriv(tanArr[3])) + ")*(sec(" + tanArr[3] + "))^2"  ))
		} // tan

	var secPos = InString.indexOf("sec");
	if (secPos == 0) {
		var secArr = parseOuterParen(InString, secPos,"(",false);
		if (isNumeric (secArr [3])) return ("0");
		else return(postFormat("("+ postFormat(stringDeriv(secArr[3])) + ")*sec(" + secArr[3] + ")*tan(" + secArr[3] + ")"  ))
		} // sec

	var cscPos = InString.indexOf("csc");
	if (cscPos == 0) {
		var cscArr = parseOuterParen(InString, cscPos,"(",false);
		if (isNumeric (cscArr [3])) return ("0");
		else return(postFormat("(-1)*("+ postFormat(stringDeriv(cscArr[3])) + ")*csc(" + cscArr[3] + ")*cot(" + cscArr[3] + ")"  ))
		} // csc

	var cotPos = InString.indexOf("cot");
	if (cotPos == 0) {
		var cotArr = parseOuterParen(InString, cotPos,"(",false);
		if (isNumeric (cotArr [3])) return ("0");
		else return(postFormat("(-1)*("+ postFormat(stringDeriv(cotArr[3])) + ")*(csc(" + cotArr[3] + "))^2"  ))
		} // cot


	var absPos = InString.indexOf("abs");
	if (absPos == 0) {
		var absArr = parseOuterParen(InString, absPos,"(",false);
		if (isNumeric (absArr [3])) return ("0");
		else return(postFormat("("+ postFormat(stringDeriv(absArr[3])) + ")*abs(" + absArr[3] + ")/(" + absArr[3] + ")"  ))
		} // abs


	var sqrtPos = InString.indexOf("sqrt");
	if (sqrtPos == 0) {
		var sqrtArr = parseOuterParen(InString, sqrtPos,"(",false);
		if (isNumeric (sqrtArr [3])) return ("0");
		else return(postFormat("("+ postFormat(stringDeriv(sqrtArr[3])) + ")/(2*sqrt(" + sqrtArr[3] + "))"  ))
		} // sqrt


	var lnPos = InString.indexOf("ln");
	if (lnPos == 0) {
		var lnArr = parseOuterParen(InString, lnPos,"(",false);
		if (isNumeric (lnArr[3])) return ("0");
		else return(postFormat("("+ postFormat(stringDeriv(lnArr[3])) + ")/(" + lnArr[3] + ")"  ))
		} // ln


	var normdPos = InString.indexOf("normalpdf");
	if (normdPos == 0) {
		var normdArr = parseOuterParen(InString, lnPos,"(",false);
		if (isNumeric (normdArr [3],",")) return ("0");
		else {
			var theStringArrayInside = "'" + replaceChar(normdArr [3],",","','") + "'";
			var theInstruction = "var normArray = [" + theStringArrayInside + "];";
			var doIt = eval(theInstruction);
			if (normArray.length == 1) {
				var theRetStr = "-(" + postFormat(stringDeriv(normdArr[3])) + ")*(" + removeOuterParen(normdArr [3]) + ")*e^(-(" + removeOuterParen(normdArr [3]) + ")^2/2)/" + (Math.sqrt(PiD2)).toString();
			return(postFormat(theRetStr));
				} // one argument only -- st norm dist
			else if (normArray.length == 2) {
				var Mu = normArray[1];
				var theRetStr = "-(" + postFormat(stringDeriv(normArray[0])) + ")*(" + removeOuterParen(normArray[0]) + "-" + Mu + ")*e^(-(" + removeOuterParen(normArray[0]) + "-" + Mu + ")^2/2)/" + (Math.sqrt(PiD2)).toString();
			return(postFormat(theRetStr));
				} // two args only -- stdev = 1
			else if (normArray.length == 3) {
				var Mu = normArray[1];
				var sig = parseFloat(normArray[2]);
				var TwoSigSq = (2*sig*sig).toString();

				var denomVal = sig*sig*sig*Math.sqrt(PiD2);		
				var theRetStr = "-(" + postFormat(stringDeriv(normArray[0])) + ")*(" + removeOuterParen(normArray[0]) + "-" + Mu + ")*e^(-(" + removeOuterParen(normArray[0]) + "-" + Mu + ")^2/" + TwoSigSq + ")/" + denomVal.toString();
			return(postFormat(theRetStr));
				} // general normal pdf
			}
	
		} // normal density


	} // nonconstant functions
return("unable to differentiate");
}

function postFormat(InString) {
InString = replaceSubstring(InString,"*(1)","");
InString = replaceSubstring(InString,"(1)*","");
InString = replaceSubstring(InString,"-(x)*","-x*");
InString = replaceSubstring(InString,"+(x)*","+x*");


// InString = removeDoubleParen(InString);
return(InString);
}

function breakApartAtOperation (InString, beginMark, opChar) {
// breaks expression apart at opChar 
// starts looking at beginMark (0 for beginning)
// that is not inside parenthesis/brackets.
// returns array: [0] = operation [1] = left part [2] = right part
// if none, then [0] term = empty string;
var L = InString.length;
var parenCount = 0;
var outArr = ["","",""];

for (var i = beginMark; i <= L; i++) {
	var tempChar = InString.charAt(i);
	if (tempChar == "(") parenCount += 1;
	else if (tempChar == ")") parenCount -= 1;
	else {
		if ((parenCount == 0) && (tempChar == opChar)) {
			//found a match
			outArr[0] = opChar;
			outArr[1] = InString.substring(beginMark,i);
			outArr[2] = InString.substring(i+1, L);
			i = L; // get out of here
			} // found an operation
		} // character is not a paren
	} // i
// alert(outArr);
return(outArr);
}

function removeOuterParen(InString) {
if (InString.indexOf("(")== -1) return(InString)
else {
	var L = InString.length;
	var testSt = parseOuterParen(InString, 0, "(", false);
	if (testSt[3] == InString.substring(1,L-1)) 	return(removeOuterParen(InString.substring(1,L-1)));
	else return(InString);
	}
}

function removeDoubleParen(InString) {
// not using this at present -- only removes the first instance...
var dpPos = InString.indexOf("((");

if (dpPos == -1) return(InString)
else {
// alert(InString.substring(dpPos+1,InString.length));
	var testSt = parseOuterParen(InString, dpPos+1, "(", false);
alert(InString.substring(dpPos, testSt[2]+1));
alert(InString.charAt(testSt[2]-1) + InString.charAt(testSt[2]));
alert(testSt[4] + testSt[3] + testSt[5]);
	if ((InString.charAt(testSt[2]-1) == ")") && (InString.charAt(testSt[2]) == ")")) {

alert("yes"); 
		return(removeDoubleParen(testSt[4] + testSt[3]) +  testSt[5]);
		}
	else return(InString);
	}

} // removeDoubleParen

// *** Error Handler ******
function myErrorTrap(message,url,linenumber) {
this.parent.bottom.window.location = "wrong.html";
return (true);
} // end of on error
// ********************


function randomSequence(n) {
// Returns an array A[i] whose ith entries are a random
// permutation of 1,..,n
var outArr = new Array();
var slot = new Array();
for (var i = 1; i <= n; i++) slot[i] = i;
for (var i = 1; i <= n; i++) {
	var j = randomInt (1,n-i+1); // number of slots left
	outArr [i] = slot [j];
	for (var k = j; k <= n-i; k++) {
		slot[k] = slot[k+1];
		} // k
	} // i
return (outArr);
} // randomSequence


function randomSequenceZero(n) {
// an array whose ith entry is a random perm of 0...n (starts at [0])
var outArr = randomSequence(n+1);
for (var i = 0; i <= n; i++) outArr [i] = outArr [i+1]-1;
return (outArr);
} // randomSequenceZero



function pickOne() {
var argArr = pickOne.arguments;
var n = argArr.length-1;
return(pickOne.arguments[randomInt(0,n)]);
}

function randomInt(a,b) {
// returns a random integer in the range [a, b]
return(a + Math.floor(Math.random()*(b-a+1)));
}

function randomNonzeroInt(a, b) {
// returns a nonzero random integer in the range [a, b]
if (a > 0) return(randomInt(a,b));
else {
	var thePick = randomInt(a,b-1);
	if (thePick >= 0) return(thePick+1);
	else return(thePick);
	}
}

function shuffle(A) {
// A can be an array of arrays.
// internally shuffles each of these arrays
var APrime = A.slice();
var len = A.length;
for (var i = 0; i <= len-1; i++) {
	var len_i = A[i].length;
	var Copy = A[i].slice();
	var P = randomSequence(len_i);
	for (var j = 0; j <= len_i-1; j++) {
		APrime[i][j] = Copy[P[j+1]-1];
		} //j
	} // i
// alert(APrime);
return(APrime);
} // shuffle

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();
    }

// ********************Old Cookie Routines **********************
var cookiesEnabled = false;
var now = new Date();
var oneDay = new Date(now.getTime() + 60000 * 60 * 24);
var oneYear = new Date(now.getTime() + 60000 * 60 * 24 * 365);
var yesterday = new Date(now.getTime() - 60000 * 60 * 24);

function cookieTest() {
// returns false if cookies are not enabled
var now = new Date();
var twosecs = new Date(now.getTime() + 1000 * 2)
setCookie('cookieTest','You will meet a tall dark stranger.', twosecs);
var testing = getCookie('cookieTest');
if(testing == null) {cookiesEnabled = false; return(false) }
else {cookiesEnabled = true; return(true) }
} // cookieTest

function setCookie (cookieName, cookieValue, expires, path, domain, 
secure) {
  document.cookie = 
    escape(cookieName) + '=' + escape(cookieValue) 
    + (expires ? '; EXPIRES=' + expires.toGMTString() : '')
    + (path ? '; PATH=' + path : '')
    + (domain ? '; DOMAIN=' + domain : '')
    + (secure ? '; SECURE' : '');
}

function getCookie (cookieName) {
  var cookieValue = null;
  var posName = document.cookie.indexOf(escape(cookieName) + '=');
  if (posName != -1) {
    var posValue = posName + (escape(cookieName) + '=').length;
    var endPos = document.cookie.indexOf(';', posValue);
    if (endPos != -1)
      cookieValue = unescape(document.cookie.substring(posValue, 
endPos));
    else
      cookieValue = unescape(document.cookie.substring(posValue));
  }
  return cookieValue;
}

// ***************** End of Old Cookie Routines *****************

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 stripChars (InString,symbolString)  {
	OutString="";
	for (Count=0; Count < InString.length; Count++)  {
		TempChar=InString.substring (Count, Count+1);
		if (symbolString.indexOf(TempChar)== -1)
			OutString=OutString+TempChar;
	}
	return (OutString);
} // stripChars


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 makeArray (NumElements, Fill)  {
	var Count;
	this.length = NumElements;
	for (Count = 1; Count <= NumElements; Count++)  {
		this[Count] = Fill;
	}
	return (this);
}

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 PARSER ***********

function evaluateFunction(theFunction, theValue, numPlaces, isSigDigits) {
// isSigDigits true gives accurate to numPlaces number of sig digits
// else accuracy numPlaces of decimal places
x = parseFloat(theValue);
var theY = myEval(theFunction);
if (isSigDigits) return parseFloat(roundSigDig(theY, numPlaces));
else return parseFloat(roundDec(theY, numPlaces));
}// 


function myEval(theString)
{
// alert(myParse(theString));
var e = Math.exp(1);
var pi = Math.PI;
return(eval(myParse(theString)))
}


// the next is an old one that can probably go
// 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 an array: [operation, left part, right part]
	// *** 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[0] = TempChar;
					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 (theChar, RefString)  {
	if(theChar.length!=1) 
		return (false);
	if (RefString.indexOf (theChar, 0)==-1) 
		return (false);
	return (true);
}



function isNumeric (sText, extraAllowedChars) {
   var ValidChars = "0123456789." + extraAllowedChars;
   var IsNumber=true;
   var Char;

 
   for (i = 0; i < sText.length && IsNumber == true; i++) 
      { 
      Char = sText.charAt(i); 
      if (ValidChars.indexOf(Char) == -1) 
         {
         IsNumber = false;
         }
      }
   return IsNumber;
  
   }



// ************** end of answer handling routines *************





// ********************** STRING UTILITIES ****************************
function parseOuterParen(InString, beginMark, parentype, backtrack) {
// returns location, left tail, right tail, and inside of a outermost matched parenthesis starting at any point
// parentype is "("  or "["  or "{"
// returns an array X[0] = -1 if none found, 1 if found
// X[1] = position of first char inside paren
// X[2] = position of last char inside paren
// X[3] = string inside
// X[4] = left tail of string outside closed paren
// X[5] = right tail of string outside closed paren
var X = new makeArray(4,0);
var L = InString.length;
var theString = "";
if (backtrack) theString = InString.substring(0,beginMark);
else theString = InString.substring(beginMark,L);
// alert (theString);
var Length = theString.length;
if (Length < 2) {X[0] = -1; return(X)}
var count = 0; 
var parenclose = ")";
if (parentype == "{") parenclose = "}";
else if (parentype == "[") parenclose = "]";
//else if (parentype == lp) parenclose = rp; // for various exotic delimiters
//else if (parentype == lb) parenclose = rb;
//else if (parentype == lbr) parenclose = rbr;
if (!backtrack)
	{
	var start = checkString(theString,parentype,backtrack);
	if (start == -1) {X[0] = -1; return(X)}
	X[1] = beginMark + start+1; // start of inside
	var parencount = 1;
// alert(start+1);
	for (var i = start+1; i <= Length; i++)
		{
		var tempChar = theString.charAt(i);
		if (tempChar == parentype) parencount++;
		else if (tempChar == parenclose) parencount--;
		if (parencount == 0) 
			{
			X[0] = 1;
			X[2] = beginMark + i; 	// just before -- at -- the last char
			X[3] = theString.substring(start+1,i);
			X[4] = InString.substring(0,X[1]-1);
			X[5] = theString.substring(X[2]-beginMark+1, Length);

// alert(X[4] + "{INSIDE IS***" + X[3] + "***}" + X[5]);
			return(X);
			}
		} // i
	} // if !backtrack
else
	{
	var end = checkString(theString, parenclose,backtrack);
	if (end == -1) {X[0] = -1; return(X)}
	X[2] = end; //end of inside
	var parencount = 1;
	for (var i = end-1; i >=0; i--)
		{
		var tempChar = theString.charAt(i);
		if (tempChar == parentype) parencount--;
		else if (tempChar == parenclose) parencount++;
		if (parencount == 0) 
			{
			X[0] = 1;
			X[1] = i+1; 	// just before -- at -- the last char
			X[3] = theString.substring(X[1],X[2]);
			X[4] = theString.substring(0,X[1]-1);
			X[5] = InString.substring(X[2]+1, L);
// alert(X[4] + "{***}" + X[5]);
			return(X);
			}
		} // i
	} // if backtrack
return(X);
}// end findParenmatch

