//	Main class///*   *	Sequences and Series Applet *	By Mike May, S.J., August 2001 *	e-mail: maymk@slu.edu * *  expr package Copyright 1996 by Darius Bacon  */// Last update 8/2/2001/* *	 *  The applet graphs a collection of sequences and their related series. *	It is designed to facilitate visual exploration of the subject. *	 *  The structure of the program has a main class SeqSeries.   *  The work is broken into a number of visible classes: *  DrawingPanel, FeedbackPanel, HelpArea, and AboutArea. *  The names of these classes are fairly self descriptive. *  This NFunction class is used to turn mathematical strings into  *	values.  It uses a parser that calls on the following classes: *  Expr, Parser, Syntax_error, Test, TrivialClass and Variable. *	The subsidaiary classes of FeedbackPanel are InputPanel, ControlPanel, *	OutputPanel, and DomainPanel. *	MultilineLabel is used by AboutArea. *	MIO is a collection of input and output routines used. *//*   * * public class SeqSeries extends Applet *	public void init() *	public boolean action(Event e, Object arg) * *	The main applet has a title label and buttons to switch between three *	cards, the main card, the help card, and the about card. *	The about card provides author information. *	The help card gives help that a user may need to run the applet. *	The main card is what we might think of as the applet proper.  It *	contains a drawing panel and a feedback panel.  The drawing panel *	and feedback panel are separate objects where most of the real work is done. * *	The init method sets up the basic interface though the most of the hard *	details are in the feedback panel and the drawing panel. * *	An action method is needed to deal with the buttons that switch cards. * * *  public void fixMain() *  public void importFeedbackPanelValues() * *	The methods of this class involve when the DrawingPanel and FeedbackPanel *	need to communicate with each other or when an action on one calls for a response *	on the other.  The majority of the work is done with the fixMain method. *	A subsidiary method of fixMain is importFeedbackPanelValues. */// java packagesimport java.applet.*;import java.awt.*;import java.lang.Math;import expr.*;			// f(x) parser by Darius Bacon						// Modified by Mike May, S.J.public class SeqSeries extends Applet{//  Declare variables	int	 	drawingPanelWidth = 470, drawingPanelHeight = 405;//	int		clickIndex = 0;  //	GUI elements   			Button 			helpButton, aboutButton, mainButton;	Label 			titleLabel;    CardLayout		theCards;    	    Panel	 		mainCd, mainPanel, cardChoicePanel;    HelpArea		helpText;    AboutArea		aboutText;    FeedbackPanel	feedbackPanel;   	DrawingPanel 	theDrawingPanel;    public void init()    {		this.setLayout(null);		resize(720,500);  	   	//	Set up the pieces		titleLabel = new Label("Sequences and Series", Label.CENTER);		setLayout(new BorderLayout(3,3));		this.add(titleLabel, BorderLayout.NORTH);		titleLabel.setFont(new Font("Dialog", Font.BOLD, 18));   	      	    mainPanel = new Panel();		this.add(mainPanel, BorderLayout.CENTER);    	// create a card layout and 3 cards    	theCards = new CardLayout(0,0);		mainPanel.setLayout(theCards); 		// create the main card 		mainCd = new Panel(); 		mainPanel.add("main",mainCd); 		mainCd.setLayout(new BorderLayout(3,3)); 		// create the about card		aboutText = new AboutArea();   	    aboutText.setBounds(0,0,600,380); 		mainPanel.add("about",aboutText); 		// create the help card		helpText = new HelpArea(600, 300);   	    helpText.setBounds(0,0,600,380); 		mainPanel.add("help",helpText);  		// create the feedback panel and add it to the main cd 		feedbackPanel = new FeedbackPanel(this);   	    feedbackPanel.setBounds(480,0,200,405);		mainCd.add(feedbackPanel, BorderLayout.EAST); 		feedbackPanel.setLayout(null);						// create the drawing panel and add it to the main cd  		theDrawingPanel = new DrawingPanel(this);		mainCd.add(theDrawingPanel, BorderLayout.CENTER);		//	move the data from feedback panel to drawing panel and initialize		feedbackPanel.collectData();		importFeedbackPanelValues();		fixMain(); 			/**	 *	Add a panel to the bottom of the screen to let the user choose	 *	between cards.	 */   	    cardChoicePanel = new Panel();   	    this.add(cardChoicePanel, BorderLayout.SOUTH);   	    cardChoicePanel.setBounds(200,460,300,20);		cardChoicePanel.setLayout(new GridLayout(1,0,10,0));		mainButton = new Button("Main Panel");		cardChoicePanel.add(mainButton);		helpButton = new Button("Help Panel");		cardChoicePanel.add(helpButton);		aboutButton = new Button("About Panel");		cardChoicePanel.add(aboutButton);		// finally, show the main card		theCards.show(mainPanel,"main");    }   // init     	// handle GUI events    public boolean action(Event e, Object arg)	{		double outputdx;     	if(e.target == aboutButton)      	{			theCards.show(mainPanel,"about");      		return true;      	}      	else if(e.target == helpButton)      	{			theCards.show(mainPanel,"help");      		return true;      	}      	else if(e.target == mainButton)      	{			theCards.show(mainPanel,"main");      	    feedbackPanel.collectData();      	    fixMain();        	paint(theDrawingPanel.getGraphics());	   		return true;      	} 		else return super.action(e,arg);		}  //  action    public void fixMain()    {		importFeedbackPanelValues();  	    theDrawingPanel.updateDrawingValues();	   	paint(getGraphics());	    theDrawingPanel.repaint();    }	//	fixMain            public void importFeedbackPanelValues()    {		theDrawingPanel.termsState 	= feedbackPanel.termsState; 		theDrawingPanel.sumsState 	= feedbackPanel.sumsState; 		theDrawingPanel.ratioState 	= feedbackPanel.ratioState; 		theDrawingPanel.pointsState = feedbackPanel.pointsState; 		theDrawingPanel.linesState 	= feedbackPanel.linesState; 		theDrawingPanel.aNState 	= feedbackPanel.aNState; 		theDrawingPanel.bNState 	= feedbackPanel.bNState; 		theDrawingPanel.geomState 	= feedbackPanel.geomState; 		theDrawingPanel.harmState	= feedbackPanel.harmState; 		theDrawingPanel.expState 	= feedbackPanel.expState;		theDrawingPanel.nStart		= feedbackPanel.nStart;	    theDrawingPanel.nGraph		= feedbackPanel.nGraph;	    theDrawingPanel.nStep 		= feedbackPanel.nStep; 		theDrawingPanel.toViewValue = feedbackPanel.toViewValue; 		theDrawingPanel.aNString 	= feedbackPanel.aNString; 		theDrawingPanel.bNString 	= feedbackPanel.bNString; 		theDrawingPanel.geomString	= feedbackPanel.geomString; 		theDrawingPanel.harmString 	= feedbackPanel.harmString;		theDrawingPanel.expString	= feedbackPanel.expString; 		theDrawingPanel.yMin 		= feedbackPanel.yMin; 		theDrawingPanel.yMax		= feedbackPanel.yMax;     }	//	importfeedbackPanelValues    }	//	SeqSeries class//////////////		Other pieces/////////* *	The drawing panel is an object for the graphical display of the applet. * *public class DrawingPanel extends Canvas *	public  DrawingPanel(SeqSeries seqSeries) * *	The constructor does little more than extend canvas and identify the applet *	and applet so that information can be passed back and forth. * * *	public void updateDrawingValues() *	public void repaint() *	public void paint(Graphics g) *	public void plotSums(Graphics g, String funcString, Color color) *	public void plotRatios(Graphics g, String funcString, Color color) *	public void plotTerms(Graphics g, String funcString, Color color) *	public void drawAxis(Graphics g) *	public void drawLimits(Graphics g) * *	The repaint method simply gets the graphics and calls paint which does all the work. *  The other methods in this group do parts of the plotting. * * *	public int yRealToPixel(double yReal) *	public int yRealToPixel(int yReal) *	public double yPixelToReal(double yPixel) *	public double yPixelToReal(int yPixel) * *	These methods switch between coordinate and pixel measurements of locations on  *	the graph *	 */ import java.awt.event.*;import java.awt.*;import java.applet.*;import MIO.*;public class DrawingPanel extends Canvas{//  Declare variables//	variables concerned with the size of the panel and how much is used //	for the actual drawing.  //	The left offset and the vertical offsets are just to //	make everything look nice.  Nothing important is graphed in the offset//	area.  The panel is set up with a single offset//	at the top and a double one at the bottom of the panel.	int	 	leftXOffset = 40,drawingPanelWidth = 470,  drawingPanelHeight = 405, YOFFSET = 20,			pointWidth, sectionCount;//	variables imported or exported to the feedback panel	boolean		termsState, sumsState, ratioState, pointsState = true, linesState = false;	boolean		aNState, bNState, geomState, harmState, expState;	int			nStart = 1, nGraph = 1, nStep, toViewValue;	String		aNString, bNString, geomString, harmString, expString;	double		yMin = -5.0, yMax = 5.0;	NFunction	func;   			SeqSeries	applet;	public  DrawingPanel(SeqSeries seqSeries)	{		super();		func = new NFunction();			pointsState = true;		linesState = false;		applet = seqSeries;	}	//	DrawingPanel	constructor   		public void updateDrawingValues()	{		drawingPanelWidth = getSize().width;		drawingPanelHeight = getSize().height;		pointWidth = (drawingPanelWidth - 2*leftXOffset)/4;		sectionCount = pointWidth/20;			}	//	updateDrawingValues	public void repaint()	{		paint(getGraphics());	}	//	repaint		public void paint(Graphics g)	{		updateDrawingValues();	//	clear the canvas		g.clearRect(0,0,drawingPanelWidth,drawingPanelHeight);	//	add axes and limits				drawAxis(g); 		drawLimits(g); 		 	// plot terms 		if(termsState == true) 		{	 		if(aNState == true) plotTerms(g, aNString, Color.red); 			if(bNState == true) plotTerms(g, bNString, Color.blue); 			if(geomState == true) plotTerms(g, geomString, Color.green); 			if(harmState == true) plotTerms(g, harmString, Color.magenta); 			if(expState == true) plotTerms(g, expString, Color.cyan);		} 	//	plot sums 		if(sumsState == true) 		{ 			if(aNState == true) plotSums(g, aNString, Color.red); 			if(bNState == true) plotSums(g, bNString, Color.blue); 			if(geomState == true) plotSums(g, geomString, Color.green); 			if(harmState == true) plotSums(g, harmString, Color.magenta); 			if(expState == true) plotSums(g, expString, Color.cyan); 		} 	//	plot ratios 		if(ratioState == true) 		{ 			if(aNState == true) plotRatios(g, aNString, Color.red); 			if(bNState == true) plotRatios(g, bNString, Color.blue); 			if(geomState == true) plotRatios(g, geomString, Color.green); 			if(harmState == true) plotRatios(g, harmString, Color.magenta); 			if(expState == true) plotRatios(g, expString, Color.cyan); 		}	}	//	paint	public void plotSums(Graphics g, String funcString, Color color)	{		int xPixel1, xPixel2, yPixel1, yPixel2, nCount;		double	sum = 0.0, temp;		func.parse(funcString);     	g.setColor(color);     	     	for(int i = nStart; i <= nGraph; i++) 		{			temp = func.value(i);			if(!(temp <= Double.POSITIVE_INFINITY)) temp = 0;			sum += temp;				}		nCount = nGraph;       	xPixel1 = leftXOffset;      	yPixel1 = yRealToPixel(sum);      	if((yPixel1 >= 0)&&(yPixel1 <= drawingPanelHeight))      	{			g.drawLine(xPixel1, yPixel1 - 2, xPixel1, yPixel1 + 2);			g.drawLine(xPixel1 - 2, yPixel1, xPixel1 + 2, yPixel1);      		      	}		for(int j = 1; j <= pointWidth; j++)		{			nCount = nGraph + (j-1)*nStep;	       	xPixel2 = leftXOffset + 4*j; 	    	for(int i = nCount + 1; i <= (nCount + nStep); i++) 			{				temp = func.value(i);				if(!(temp <= Double.POSITIVE_INFINITY)) temp = 0;				sum += temp;					}	      	yPixel2 = yRealToPixel(sum);	      	if((yPixel2 >= 0)&&(yPixel2 <= drawingPanelHeight))	      	{				g.drawLine(xPixel2, yPixel2 - 2, xPixel2, yPixel2 + 2);				g.drawLine(xPixel2 - 2, yPixel2, xPixel2 + 2, yPixel2);    			      	}			if(pointsState == false)			{				if(  ((0 <= yPixel2) && (yPixel2 <= drawingPanelHeight)) ||					 ((0 <= yPixel1) && (yPixel1 <= drawingPanelHeight)) ) 					 	g.drawLine(xPixel1, yPixel1, xPixel2, yPixel2);						}	      	xPixel1 = xPixel2;	      	yPixel1 = yPixel2;					}      		}		//	plotSums		public void plotRatios(Graphics g, String funcString, Color color)	{		int xPixel1, xPixel2, yPixel1, yPixel2, nCount;		double temp, ytemp1, ytemp2;				func.parse(funcString);     	g.setColor(color);		nCount = nGraph;       	xPixel1 = leftXOffset;       	ytemp1 = func.value(nCount);       	ytemp2 = func.value(nCount + 1);		if(!(ytemp1 <= Double.POSITIVE_INFINITY))temp = 0; 		else temp = ytemp2/ytemp1;      	yPixel1 = yRealToPixel(temp);      	if((yPixel1 >= 0)&&(yPixel1 <= drawingPanelHeight))      	{			g.drawLine(xPixel1, yPixel1 - 2, xPixel1, yPixel1 + 2);			g.drawLine(xPixel1 - 2, yPixel1, xPixel1 + 2, yPixel1);       	}		for(int i = 1; i <= pointWidth; i++)		{			nCount = nGraph + i*nStep;	       	xPixel2 = leftXOffset + 4*i;	       	ytemp1 = func.value(nCount);	       	ytemp2 = func.value(nCount + 1);			if(!(ytemp1 <= Double.POSITIVE_INFINITY))temp = 0; 			else temp = ytemp2/ytemp1;  	    	yPixel2 = yRealToPixel(temp);	      	if((yPixel2 >= 0)&&(yPixel2 <= drawingPanelHeight))	      	{				g.drawLine(xPixel2, yPixel2 - 2, xPixel2, yPixel2 + 2);				g.drawLine(xPixel2 - 2, yPixel2, xPixel2 + 2, yPixel2);    			      	}			if(pointsState == false)			{				if(  ((0 <= yPixel2) && (yPixel2 <= drawingPanelHeight)) ||					 ((0 <= yPixel1) && (yPixel1 <= drawingPanelHeight)) ) 					 	g.drawLine(xPixel1, yPixel1, xPixel2, yPixel2);						}	      	xPixel1 = xPixel2;	      	yPixel1 = yPixel2;					}      		}		//	plotRatios		public void plotTerms(Graphics g, String funcString, Color color)	{		int xPixel1, xPixel2, yPixel1, yPixel2, nCount;		double temp;				func.parse(funcString);     	g.setColor(color);		nCount = nGraph;       	xPixel1 = leftXOffset;      	yPixel1 = yRealToPixel(func.value(nCount));      	if((yPixel1 >= 0)&&(yPixel1 <= drawingPanelHeight))      	{			g.drawLine(xPixel1, yPixel1 - 2, xPixel1, yPixel1 + 2);			g.drawLine(xPixel1 - 2, yPixel1, xPixel1 + 2, yPixel1);      		      	}		for(int i = 1; i <= pointWidth; i++)		{			nCount = nGraph + i*nStep;	       	xPixel2 = leftXOffset + 4*i;			temp = func.value(nCount);			if(!(temp <= Double.POSITIVE_INFINITY)) temp = 0;	      	yPixel2 = yRealToPixel(temp);	      	if((yPixel2 >= 0)&&(yPixel2 <= drawingPanelHeight))	      	{				g.drawLine(xPixel2, yPixel2 - 2, xPixel2, yPixel2 + 2);				g.drawLine(xPixel2 - 2, yPixel2, xPixel2 + 2, yPixel2);    			      	}			if(pointsState == false)			{				if(  ((0 <= yPixel2) && (yPixel2 <= drawingPanelHeight)) ||					 ((0 <= yPixel1) && (yPixel1 <= drawingPanelHeight)) ) 					 	g.drawLine(xPixel1, yPixel1, xPixel2, yPixel2);						}	      	xPixel1 = xPixel2;	      	yPixel1 = yPixel2;					}      		}		//	plotTerms		// draw the axis	public void drawAxis(Graphics g)	{	    int xAxisPixel, yAxisPixel, yPixel;       		  	g.setColor(Color.black); 	  	 	  	xAxisPixel = yRealToPixel(0); 	  	if(xAxisPixel > drawingPanelHeight - 50) xAxisPixel = drawingPanelHeight - 50; 	  	if(xAxisPixel < 28) xAxisPixel = 28; 	  	yAxisPixel = leftXOffset;				// x axis        g.drawLine(20,xAxisPixel,drawingPanelWidth - 20,xAxisPixel);	                if (ratioState == true)        {        	int onePixel = yRealToPixel(1.0);        	g.drawLine(0,onePixel,drawingPanelWidth - 20,onePixel);		  	g.setColor(Color.red); 	 		g.drawString("1",drawingPanelWidth - 15,onePixel + 4);		  	g.setColor(Color.black);        	onePixel = yRealToPixel(-1.0);        	g.drawLine(0,onePixel,drawingPanelWidth - 20,onePixel);		  	g.setColor(Color.red); 	 		g.drawString("-1",drawingPanelWidth - 15,onePixel + 4);		  	g.setColor(Color.black);        }         // y axis        for(int i = 0; i <= sectionCount; i++)        {        yPixel = leftXOffset + i*80;        g.drawLine(yPixel,20,yPixel,drawingPanelHeight-10);        }                g.drawString("n", 5,xAxisPixel + 4);        g.drawString("0",drawingPanelWidth - 15,xAxisPixel + 4);        g.drawString("Y",yAxisPixel-2,17); 	}  //  drawAxis	// draw limits in the proper places	public void drawLimits(Graphics g)	{      	int xAxisPixel, yAxisPixel, xMaxPixel, xMidPixel, yPixel;      	int xBasePixel, x1Pixel;      	double yVal;      	xAxisPixel = (int) yRealToPixel(0); 	  	if(xAxisPixel > drawingPanelHeight - 50) xAxisPixel = drawingPanelHeight - 50; 	  	if(xAxisPixel < 28) xAxisPixel = 28;      	yAxisPixel = leftXOffset;      	xMidPixel  = leftXOffset + 200;      	xMaxPixel  = leftXOffset + 400;      	g.setColor(Color.red);				// x limit		for (int i = 0; i <= sectionCount/2; i++)		{		g.drawString(Integer.toString(nGraph + i*40*nStep), yAxisPixel + 4 +i*160 ,xAxisPixel + 14);		g.drawLine(yAxisPixel,xAxisPixel +i*160 - 2, yAxisPixel,xAxisPixel +i*160 + 2);		}				// y limit		yVal = yMax;		yPixel = yRealToPixel(yVal);		g.drawString(Mio.doubleToStringSigFigures(yVal, 4), yAxisPixel - 40,yPixel + 3);		g.drawLine(yAxisPixel - 2,yPixel, yAxisPixel + 2,yPixel);				yVal = yMin;		yPixel = yRealToPixel(yVal);		g.drawString(Mio.doubleToStringSigFigures(yVal, 4), yAxisPixel - 40,yPixel + 3);		g.drawLine(yAxisPixel - 2,yPixel, yAxisPixel + 2,yPixel);				  	}  //  drawLimits			// input real value, output pixel in interval [0, YSCALE]	public int yRealToPixel(double yReal)	{		return (int)((yReal - yMax) * (drawingPanelHeight - 3*YOFFSET) / 		         (yMin - yMax) + YOFFSET);	}  //  yRealToPixel	public int yRealToPixel(int yReal)	{		return (int)((yReal - yMax) * (drawingPanelHeight - 3*YOFFSET) / 		        (yMin - yMax) + YOFFSET);	}  //  yRealToPixel	// input pixel, output real in interval [yMin, yMax]	public double yPixelToReal(double yPixel)	{		return ((yPixel - YOFFSET) * (yMin - yMax) / 		        (drawingPanelHeight - 3*YOFFSET) + yMax);	}  //  yPixelToReal	public double yPixelToReal(int yPixel)	{		return ((yPixel - YOFFSET) * (yMin - yMax) / 		        (drawingPanelHeight - 3*YOFFSET) + yMax);	}  //  yPixelToReal}	//	DrawingPanel class// NFunction Class/*  Modified by Mike May,  August 2001 *	 *	 *public class NFunction *	public NFunction() *	public void parse( String f ) *	 *	The class NFuncttion is a is used to evaluate a function in n. *	the parse method sends the string over to the Parser class for parsing *	 * *	public double value(double n) *	 *	These method evaluates the function at n. */// java packagesimport java.applet.*;import java.awt.*;import java.lang.Math;import expr.*;	// expr package Copyright 1996 by Darius Baconpublic class NFunction{	//	created for access to infinity constants	Double doubleCheck = new Double(1.0);	 	public Expr expr;	public Variable nvar;	public NFunction()	{		// set up the parsing variables		nvar = Variable.make("n");		Variable.make("pi").set_value (Math.PI);			Variable.make("PI").set_value (Math.PI);			Variable.make("Pi").set_value (Math.PI);			Variable.make("e").set_value (Math.exp(1));	/* * 	¹ and e are not in the parsing constructor */	}  //  NFunction constructor		/*	 *	Parse the function	 */	 	public void parse( String f ) 	{	   	try	   	{expr = Parser.parse(f);}		catch (Syntax_error se)		{			System.err.println ("Syntax error: " + se);			return;		}	}  // parse		public double value(double n)	{		nvar.set_value(n);		return expr.value();	}  //  value	} // end of NFunction Class/* *	The feedback panel is intended to contain all the inputs and text *	outputs used by the applet.   * *public class FeedbackPanel extends Panel *	public FeedbackPanel(SeqSeries seqSeries) *	public void collectData() *	public void internalFeedbackPanelComputations() *	public String evalTerm(String name, NFunction f, int m) *	public String evalSum(String name, NFunction f, int m) *	public void update() *  public void getInputValues() *	public void sendInputValues() *  public void getDomainValues() *	public void sendDomainValues() *  public void getControlValues() *	public void sendOutputValues() * *	It is broken into four subpanels, one each for: user supplied inputs, *	the domain and range of the graph, control values of what will be graphed, *	and for output.  There may be a get and send method for each subpanel. *	The fixInputs method collects data from all panels.  The *	internalFeedbackPanelComputations method does the obvious things. *	The methods evalTerm and evalSum are subsidiary methods to  *	internalFeedbackPanelComputations. *	The update method is there to invoke methods in the calling applet *	that contains the FeedbackPanel. * * *public class InputPanel extends Panel *	public InputPanel(FeedbackPanel fPanel) *  public boolean action(Event e, Object arg) *	public void collectInputValues() *	public void postInputValues() * *public class ControlPanel extends Panel *	public ControlPanel(FeedbackPanel fPanel) *	class SymItem implements java.awt.event.ItemListener *		public void itemStateChanged(java.awt.event.ItemEvent event) *	public void collectControlValues() * *public class OutputPanel extends Panel *	public OutputPanel() *	public void postOutput() * *public class DomainPanel extends Panel *	public DomainPanel(FeedbackPanel fPanel) *  public boolean action(Event e, Object arg) *	public void postDomainValues() *	public void collectDomainValues() * * *	In addition to its constructor, each of the four subpanels may have an action *	listener and methods to collect and post data. */import java.awt.*;import java.applet.*;import MIO.*;public class FeedbackPanel extends Panel{	/*	 *		Public variables that are either inputs or outputs to be passed	 */	boolean		termsState, sumsState, ratioState, pointsState, linesState;	boolean		aNState, bNState, geomState, harmState, expState;	int			nStart = 1, nGraph = 1, nStep, toViewValue;	String		aNString, bNString, geomString, harmString, expString;	String		string1a, string1b, string2a, string2b, string3a, string3b,				string4a, string4b, string5a, string5b;	double		aNSum, bNSum, geomSum, harmSum, kharmSum;	double		yMin = -5.0, yMax = 5.0;	NFunction	nFunc;//    ZFunction	f;  	InputPanel		inputPanel;	ControlPanel	controlPanel;	OutputPanel		outputPanel;	DomainPanel		domainPanel;	SeqSeries 		applet;		public FeedbackPanel(SeqSeries sumSeries)	{		this.setLayout(null);		applet = sumSeries;    	    inputPanel = new InputPanel(this);    	inputPanel.setBounds(0,0,200,120); 		inputPanel.setLayout(null);		this.add(inputPanel);   	    outputPanel = new OutputPanel();    	outputPanel.setBounds(0,120,200,160); 		outputPanel.setLayout(new GridLayout(0,1,0,0));		this.add(outputPanel);   	    controlPanel = new ControlPanel(this);    	controlPanel.setBounds(0,280,200,60); 		controlPanel.setLayout(null);		this.add(controlPanel);   	    domainPanel = new DomainPanel(this);   	    domainPanel.setBounds(0, 340, 200, 60);  		domainPanel.setLayout(null);		this.add(domainPanel);				nFunc = new NFunction();	}	//	FeedbackPanel	//		Gather the inputs - main collection method		public void collectData()    {			getInputValues();			getDomainValues();			getControlValues();			internalFeedbackPanelComputations();			sendOutputValues();    }	//	  collectData	public void internalFeedbackPanelComputations()	{    	string1a = " ";		string1b = " ";		if(aNState == true)		{			nFunc.parse(aNString);   		 	string1a = evalTerm("A",nFunc,toViewValue);			string1b = evalSum("A",nFunc,toViewValue);		}    	string2a = " ";		string2b = " ";		if(bNState == true)		{			nFunc.parse(bNString);   		 	string2a = evalTerm("B",nFunc,toViewValue);			string2b = evalSum("B",nFunc,toViewValue);		}    	string3a = " ";		string3b = " ";		if(geomState == true)		{			nFunc.parse(geomString);   		 	string3a = evalTerm("G",nFunc,toViewValue);			string3b = evalSum("G",nFunc,toViewValue);		}    	string4a = " ";		string4b = " ";		if(harmState == true)		{			nFunc.parse(harmString);   		 	string4a = evalTerm("H",nFunc,toViewValue);			string4b = evalSum("H",nFunc,toViewValue);		}    	string5a = " ";		string5b = " ";		if(expState == true)		{			nFunc.parse(expString); 		 	string5a = evalTerm("E",nFunc,toViewValue);			string5b = evalSum("E",nFunc,toViewValue);		}	}	//	internalFeedbackPanelComputations			public String evalTerm(String name, NFunction f, int m)	{		double temp = f.value(m);		if(!(temp <= Double.POSITIVE_INFINITY)) temp = 0.0;		return "("+name+", "+m+") = "+ Mio.doubleToStringSigFigures(temp,7) ;	}	//	evalTerm		public String evalSum(String name, NFunction f, int m)	{		double	sum = 0.0, temp = 0.0;		for(int i = nStart; i <= toViewValue; i++) 		{			temp = f.value(i);			if(!(temp <= Double.POSITIVE_INFINITY)) temp = 0;			sum += temp;				}		return "S("+name+", "+m+") = "+ Mio.doubleToStringSigFigures(sum, 7);	}	//	evalSum	public void update()	{	      	applet.fixMain();	}	//	update		    //		Methods for communicating with subsidiary objects    public void getInputValues()    {   	    inputPanel.collectInputValues();		aNState			= inputPanel.aNState;		bNState			= inputPanel.bNState;		geomState		= inputPanel.geomState;		harmState		= inputPanel.harmState;		expState		= inputPanel.expState;		aNString		= inputPanel.aNString;		bNString		= inputPanel.bNString;		geomString		= inputPanel.geomString;		harmString		= inputPanel.harmString;		expString		= inputPanel.expString;		toViewValue		= inputPanel.toViewValue;    }	//	getInputValues	public void sendInputValues()	{		inputPanel.postInputValues();	}	//	sendInputValues	    public void getDomainValues()    {	    domainPanel.collectDomainValues();		nStart = domainPanel.nStart;		nGraph = domainPanel.nGraph;		nStep  = domainPanel.nStep;		yMin = domainPanel.yMin;		yMax = domainPanel.yMax;    }	//	getDomainValues	public void sendDomainValues()	{		domainPanel.postDomainValues();	}	//	sendDomainValues	    public void getControlValues()    {	    controlPanel.collectControlValues();		termsState 		= controlPanel.termsState;		sumsState 		= controlPanel.sumsState;		ratioState 		= controlPanel.ratioState;		pointsState 	= controlPanel.pointsState;		linesState 		= controlPanel.linesState;    }	//	getControlValues	public void sendOutputValues()	{ 		outputPanel.string1a 		= string1a;		 		outputPanel.string1b 		= string1b;		 		outputPanel.string2a 		= string2a;		 		outputPanel.string2b 		= string2b;		 		outputPanel.string3a 		= string3a;		 		outputPanel.string3b 		= string3b;		 		outputPanel.string4a 		= string4a;		 		outputPanel.string4b 		= string4b;		 		outputPanel.string5a 		= string5a;		 		outputPanel.string5b 		= string5b;		 		outputPanel.postOutput();			}  //sendOutputValues }	//	FeedbackPanel class////	Start new subsidiary classpublic class InputPanel extends Panel{	/*	 *		Public variables that are either inputs or outputs to be passed	 */	boolean		aNState, bNState, geomState, harmState, expState;	String		aNString, bNString, geomString, harmString, expString;	double		geoConstant, geoBase, harmConstant, expBase;	int			toViewValue;	  	/*	 *		GUI elements for the panel	 */			Label		aNLabel, bNLabel, geomLabel, geomLabel2, geomLabel3, 				harmLabel, harmLabel2, expLabel, expLabel2, toViewLabel;	TextField	aNField, bNField, geomField, geomField2, harmField, 				expField, toViewField;	Checkbox	aNBox, bNBox, geomBox, harmBox, expBox;	FeedbackPanel  feedbackPanel;		public InputPanel(FeedbackPanel fPanel)	{		feedbackPanel = fPanel;		aNBox = new Checkbox(null, true);		aNBox.setBounds(0,0,18,18);		aNBox.setBackground(Color.red);		this.add(aNBox);		aNLabel = new Label("A(n) = ");		aNLabel.setBounds(20,0,35,18);		this.add(aNLabel);		aNField = new TextField("3/n^2", 30);		aNField.setBounds(60,0,140,18);		this.add(aNField);		bNBox = new Checkbox(null, true);		bNBox.setBounds(0,20,18,18);		bNBox.setBackground(Color.blue);		this.add(bNBox);		bNLabel = new Label("B(n) = ");		bNLabel.setBounds(20,20,35,18);		this.add(bNLabel);		bNField = new TextField("(-1)^n/n", 30);		bNField.setBounds(60,20,140,18);		this.add(bNField);		geomBox = new Checkbox(null, true);		geomBox.setBounds(0,40,18,18);		geomBox.setBackground(Color.green);		this.add(geomBox);		geomLabel = new Label("G(n) = ");		geomLabel.setBounds(20,40,35,18);		this.add(geomLabel);		geomField = new TextField("2.5", 30);		geomField.setBounds(60,40,40,18);		this.add(geomField);		geomLabel2 = new Label(" * ");		geomLabel2.setBounds(100,40,20,18);		this.add(geomLabel2);		geomField2 = new TextField(".75", 30);		geomField2.setBounds(120,40,40,18);		this.add(geomField2);		geomLabel3 = new Label(" ^n");		geomLabel3.setBounds(160,40,20,18);		this.add(geomLabel3);		harmBox = new Checkbox(null, true);		harmBox.setBounds(0,60,18,18);		harmBox.setBackground(Color.magenta);		this.add(harmBox);		harmLabel = new Label("H(n) = ");		harmLabel.setBounds(20,60,35,18);		this.add(harmLabel);		harmField = new TextField("2", 30);		harmField.setBounds(60,60,40,18);		this.add(harmField);		harmLabel2 = new Label(" * 1/n ");		harmLabel2.setBounds(100,60,40,18);		this.add(harmLabel2);		expBox = new Checkbox(null, true);		expBox.setBounds(0,80,18,18);		expBox.setBackground(Color.cyan);		this.add(expBox);		expLabel = new Label("E(n) = ");		expLabel.setBounds(20,80,35,18);		this.add(expLabel);		expField = new TextField("ln(3)", 30);		expField.setBounds(60,80,40,18);		this.add(expField);		expLabel2 = new Label(" ^n/fact(n) ");		expLabel2.setBounds(100,80,60,18);		this.add(expLabel2);		toViewLabel = new Label("n to view = ");		toViewLabel.setBounds(0,100,55,18);		this.add(toViewLabel);		toViewField = new TextField("100", 30);		toViewField.setBounds(60,100,100,18);		this.add(toViewField);		SymItem lSymItem = new SymItem();		aNBox.addItemListener(lSymItem);		bNBox.addItemListener(lSymItem);		geomBox.addItemListener(lSymItem);		harmBox.addItemListener(lSymItem);		expBox.addItemListener(lSymItem); 			}	//	InputPanel// handle GUI events	//	listen for changes in checkboxes		class SymItem implements java.awt.event.ItemListener	{		public void itemStateChanged(java.awt.event.ItemEvent event)		{       	    feedbackPanel.collectData();      	    feedbackPanel.update();    	}	}	//	SymItem class		//	listen for button pushes and returns in text fields    public boolean action(Event e, Object arg)	{      	if(	(e.target == aNField)||(e.target == bNField)||      		(e.target == geomField)||(e.target == geomField2)||(e.target == harmField)||      		(e.target == expField)||(e.target == toViewField) )      	{     	    feedbackPanel.collectData();    		feedbackPanel.update();      		return true;      	} 		else return super.action(e,arg);		}  //  action//		Gather the inputs - main collection method		public void collectInputValues()    {    	aNString 		= aNField.getText();    	bNString 		= bNField.getText();	    	geoConstant		= Mio.doubleFromTextField(geomField);	   	if(geoConstant == 0) geomField.setText("0");    	geoBase			= Mio.doubleFromTextField(geomField2);	   	if(geoBase == 0) geomField2.setText("0");	   	geomString = geomField.getText() + "*(" + geomField2.getText() + ")^n";    	harmConstant	= Mio.doubleFromTextField(harmField);	   	if(harmConstant == 0) harmField.setText("0");	   	harmString = harmField.getText() + "/n";    	expBase	= Mio.doubleFromTextField(expField);	   	if(expBase == 0) expField.setText("0");	   	expString = "(" + expField.getText() + ")^n/fact(n)";    	toViewValue		= Mio.intFromTextField(toViewField);    	if(toViewValue == 0) toViewField.setText("0");		aNState	= aNBox.getState();		bNState	= bNBox.getState();		geomState	= geomBox.getState();		harmState	= harmBox.getState();		expState	= expBox.getState();    }	//	  collectInputValues	public void postInputValues()    {    }	//	  postInputValues}		//		InputPanel class////	Start new subsidiary classpublic class ControlPanel extends Panel{	/*	 *		Public variables that are either inputs or outputs to be passed	 */	boolean		termsState, sumsState, ratioState, pointsState, linesState;  	/*	 *		GUI elements for the panel	 */		Checkbox	termsBox, sumsBox, ratioBox, pointsBox, linesBox;	FeedbackPanel  feedbackPanel;	public ControlPanel(FeedbackPanel fPanel)	{		feedbackPanel = fPanel; 				termsBox = new Checkbox("Terms ", false);		termsBox.setBounds(0,0,60,18);		this.add(termsBox);		sumsBox = new Checkbox("Sums ", true);		sumsBox.setBounds(70,0,60,18);		this.add(sumsBox);		ratioBox = new Checkbox("Ratios ", false);		ratioBox.setBounds(140,0,60,18);		this.add(ratioBox);		CheckboxGroup printGroup = new CheckboxGroup();		pointsBox = new Checkbox("Points ", printGroup, true);		pointsBox.setBounds(0,20,90,18);		this.add(pointsBox);		linesBox = new Checkbox("Lines ", printGroup, false);		linesBox.setBounds(100,20,90,18);		this.add(linesBox);		SymItem lSymItem = new SymItem();		termsBox.addItemListener(lSymItem);		sumsBox.addItemListener(lSymItem);		ratioBox.addItemListener(lSymItem);		pointsBox.addItemListener(lSymItem);		linesBox.addItemListener(lSymItem);	}	//	ControlPanel// handle GUI events	//	listen for changes in menues		class SymItem implements java.awt.event.ItemListener	{		public void itemStateChanged(java.awt.event.ItemEvent event)		{       	    feedbackPanel.collectData();      	    feedbackPanel.update();    	}	}	//	SymItem class	//		Gather the inputs - main collection method		public void collectControlValues()    {		termsState 	= termsBox.getState();		sumsState	= sumsBox.getState();		ratioState	= ratioBox.getState();		pointsState = pointsBox.getState();		linesState 	= linesBox.getState();    }	//	  collectControlValues}	//	ControlPanel class////	Start new subsidiary classpublic class OutputPanel extends Panel{	/*	 *		Public variables that are either inputs or outputs to be passed	 */	String	string1a = " ", string1b = " ", string2a = " ", string2b = " ", 			string3a = "3a", string3b = "3b",			string4a = "4a", string4b = " ", string5a = " ", string5b = " ";  	/*	 *		GUI elements for the panel	 */		Label 	label1a, label1b, label2a, label2b, label3a, label3b,			label4a, label4b, label5a, label5b;		public OutputPanel()	{		label1a = new Label();		label1a.setForeground(Color.red);		this.add(label1a);		label1b = new Label();		label1b.setForeground(Color.red);		this.add(label1b);		label2a = new Label();		label2a.setForeground(Color.blue);		this.add(label2a);		label2b = new Label();		label2b.setForeground(Color.blue);		this.add(label2b);		label3a = new Label();		label3a.setForeground(Color.green);		this.add(label3a);		label3b = new Label();		label3b.setForeground(Color.green);		this.add(label3b);		label4a = new Label();		label4a.setForeground(Color.magenta);		this.add(label4a);		label4b = new Label();		label4b.setForeground(Color.magenta);		this.add(label4b);		label5a = new Label();		label5a.setForeground(Color.cyan);		this.add(label5a);		label5b = new Label();		label5b.setForeground(Color.cyan);		this.add(label5b);	}	//	OutputPanel		public void postOutput()	{//		Adjust with round to get desired precision		label1a.setText(string1a);		label1b.setText(string1b);		label2a.setText(string2a);		label2b.setText(string2b);		label3a.setText(string3a);		label3b.setText(string3b);		label4a.setText(string4a);		label4b.setText(string4b);		label5a.setText(string5a);		label5b.setText(string5b);	}  //	postOutput }	//	class OutputPanel////	Start new subsidiary classpublic class DomainPanel extends Panel // Unchanged{	/*	 *		Public variables that are either inputs or outputs to be passed	 */	double  yMin = -5.0, yMax = 5.0;	int		nStart = 1, nGraph = 1, nStep = 1; 	/*	 *		Variables that are used in internal computations	 */    double	xCenter, halfWide, yCenter, halfHigh;  	/*	 *		GUI elements for the panel	 */			Button		yIn, yOut;//	Button		zoomIn, zoomOut, yIn, yOut;	Label   	nStartLabel, nGraphLabel, nStepLabel, yMinLabel, yMaxLabel;     TextField 	nStartField, nGraphField, nStepField, yMinField, yMaxField; 	FeedbackPanel  feedbackPanel;		public DomainPanel(FeedbackPanel fPanel)	{		this.setLayout(null);		feedbackPanel = fPanel;//  	Assume panel is 200 by 60 		nStartLabel = new Label("n Start =");   	    nStartLabel.setBounds(0, 0, 45, 18);		this.add(nStartLabel);		nStartField = new TextField("1", 7);   	    nStartField.setBounds(50, 0, 45, 18);		this.add(nStartField);		nGraphLabel = new Label("nGraph =");   	    nGraphLabel.setBounds(0, 20, 45, 18);		this.add(nGraphLabel);		nGraphField = new TextField("1", 7);   	    nGraphField.setBounds(50, 20, 45, 18);		this.add(nGraphField);		nStepLabel = new Label("n Step =");   	    nStepLabel.setBounds(0, 40, 45, 18);		this.add(nStepLabel);		nStepField = new TextField("1", 7);   	    nStepField.setBounds(50, 40, 45, 18);		this.add(nStepField); 		yIn = new Button("Y In");    	yIn.setBounds(105,40,40,14);		this.add(yIn); 		yOut = new Button("Y Out");    	yOut.setBounds(150,40,40,14);		this.add(yOut);		yMaxLabel = new Label("yMax =");   	    yMaxLabel.setBounds(100, 0, 40, 18);		this.add(yMaxLabel);		yMaxField = new TextField("10.0", 7);   	    yMaxField.setBounds(140, 0, 60, 18);		this.add(yMaxField); 		yMinLabel = new Label("yMin =");   	    yMinLabel.setBounds(100, 20, 40, 18);		this.add(yMinLabel);		yMinField = new TextField("-10.0", 7);   	    yMinField.setBounds(140, 20, 60, 18);		this.add(yMinField);	}	//	DomainPanel	//	listen for button pushes and returns in text fields    public boolean action(Event e, Object arg)	{      	if((e.target == nStartField)||(e.target == nGraphField)||      	   (e.target == nStepField)||(e.target == yMinField)||      	   (e.target == yMaxField))      	{       	    feedbackPanel.collectData();      	    feedbackPanel.update();      		return true;      	}     	   		if(e.target == yIn)      	{       		yCenter = (yMax + yMin)/2;      		halfHigh = yMax - yCenter;			yMin = yCenter - halfHigh/2.0;			yMax = yCenter + halfHigh/2.0;      	    postDomainValues();       	    feedbackPanel.collectData();      	    feedbackPanel.update();      		return true;      	}   		if(e.target == yOut)      	{      		yCenter = (yMax + yMin)/2;      		halfHigh = yMax - yCenter;			yMin = yMin - halfHigh;			yMax = yMax + halfHigh;      	    postDomainValues();       	    feedbackPanel.collectData();      	    feedbackPanel.update();      		return true;      	} 		else return super.action(e,arg);		}  //  action	public void postDomainValues()	{		nStartField.setText(String.valueOf(nStart));		nGraphField.setText(String.valueOf(nGraph));		nStepField.setText(String.valueOf(nStep));		yMinField.setText(Mio.doubleToStringSigFigures(yMin,5));		yMaxField.setText(Mio.doubleToStringSigFigures(yMax,5));	}	//	postDomainValues		public void collectDomainValues()	{	    nStart=Mio.intFromTextField(nStartField);	   	nGraph=Mio.intFromTextField(nGraphField);		if((nGraph < nStart)||(nGraph > nStart + 100000))		{			System.out.println("Warning, nGraph must be between");			System.out.println("nStart and nStart + 100,000");			nGraph = nStart;			nGraphField.setText(Integer.toString(nGraph));		}	   	nStep=Mio.intFromTextField(nStepField);		if((nStep < 1)||(nStep > 1000))		{			System.out.println("Warning, nStep must be between");			System.out.println("1 and 1000");			nStep = 1;			nStepField.setText(Integer.toString(nStep));		}    	//  Check that xMin < xMax and set them    	yMin=Mio.doubleFromTextField(yMinField);    	yMax=Mio.doubleFromTextField(yMaxField);    	if (yMax <= yMin)        	{       	  System.out.println("Warning, yMin should be < yMax");       	  System.out.println("xMin and xMax reset to defaults.");       		yMin = -5.0;       		yMax = 5.0;       	}       	postDomainValues();    }  //  collectDomainValues	}	//	DomainPanelClass//	End of FeedbackPanel File/* *	Help are is a simple object to be used for the help panel of the applet. *	It is set up as a scrolling region in case the help text is made long *	enough to require that, but the default is that no scrollbars are visible. */import java.awt.TextArea;public class HelpArea extends TextArea{	public HelpArea(int width, int height)	{//Scrollbar visibility - 0 = both, 1= vert only, 2=horizon only, 3 = none//		super(String text, int width, int height, int scrollbarVisibility)		super(" ", width, height, 1);			this.setText(		"This applet is designed to explore sequences and series and they would be\n" +		"used in a typical calculus course.  They can be explored both numerically\n" +		"by looking at the value at a particular n and graphically, looking at 100\n" +		"values together.\n\n" +		"The applet lets the user choose to see graphs of terms, or sums, or ratios of terms.\n\n" +		"The obvious first point is that convergent series typically have graphs that look \n" +		"convergent while divergent series never do settle down.\n\n" +		"The user can set nStart, where the sequence starts, nGraph, where the graph starts,\n" +		"and nStep, the distance between graphical steps.  The value of nGraph should be \n" +		"within 100,000 of nStart.  The value of nStep must be between 1 and 1,000.\n\n" +		"The applet will display information on up to 5 sequences.  The first two of the\n" +		"sequences are user defined.  For the remaining three, the user sets parameters\n" +		"for sequences that typically are of importance in the study of sequences and\n" +		"series, namely a geometric sequence, a harmonic sequence, and a sequence for \n" +		"the Taylor series of the exponential function.\n\n" +		"The two user specified sequences should be expressions in n.\n\n" +		"The function should be an expression in n.  Implicit multiplication is not allowed.\n" +		"(Use 3*x rather than 3x.)  Exponentiation is indicated by ^.  \n" +		"The mathematical constant pi can be in upper or lower case.\n" +  		"The constant e is indicated by either e or exp(1).\n" + 		"(These constants only have double precision,  Thus e^x will only appoximate exp(x).\n" + 		"Trig functions are in radians.  Use the functions toDegrees and toRadians to convert.\n\n" +		"The functions understood by the parser are:\n" +		"sin,  cos, tan, sec, csc, acos or arccos, asin or arcsin, atan or arctan, \n" +		"toDegrees, toRadians, abs, ceil, fact, floor, round,\n" +		"sqrt, exp, log or ln (for natural log), and log10.\n\n" +		"Each of these functions requires one argument enclosed in parentheses.\n\n" +		"It should be noted that the applet cheats on some computations.\n" +		"Standard sequences often include terms like (c^n)/(n!) which becomes of\n" +		"quotient of terms outside the bounds for java computations on decimal values.\n" +		"This applet considers such terms to be zero.");		this.setEditable(false);	}}	//	HelpArea/* *	AboutArea is an object for the About Panel.  It is a multi-line label *	with a fixed text message. */import java.awt.*;public class AboutArea extends MultiLineLabel{	Font theFont = new Font("TimesRoman", Font.BOLD, 18);	String label = "Sequence and Series Applet\n \n"+			"Copyright 2001 by Mike May, S.J.\n"+			"maymk@slu.edu\n \n"+			"Function Parsing Copyright 1996 by Darius Bacon";	int		alignment = 1;		//	center	int		margin_width =10, margin_height = 10;	public AboutArea(){//		super(label, margin_width, margin_height, alignmnet);//		Possible alignment values are 0 for left, 1 for center and 2 for right.		super(" ", 10,10, 1);		this.setLabel(label);		this.setFont(theFont);	}}	//	AboutArea//	MultiLineLabel// This example is from _Java Examples in a Nutshell_. (http://www.oreilly.com)// Copyright (c) 1997 by David Flanagan// This example is provided WITHOUT ANY WARRANTY either expressed or implied.// You may study, use, modify, and distribute it for non-commercial purposes.// For any commercial use, see http://www.davidflanagan.com/javaexamplesimport java.awt.*;import java.util.*;/** * A custom component that displays multiple lines of text with specified * margins and alignment.  In Java 1.1, we could extend Component instead * of Canvas, making this a more efficient "Lightweight component" */public class MultiLineLabel extends Canvas {  // User-specified attributes  protected String label;             // The label, not broken into lines  protected int margin_width;         // Left and right margins  protected int margin_height;        // Top and bottom margins  protected int alignment;            // The alignment of the text.  public static final int LEFT = 0, CENTER = 1, RIGHT = 2; // alignment values  // Computed state values  protected int num_lines;            // The number of lines  protected String[] lines;           // The label, broken into lines  protected int[] line_widths;        // How wide each line is  protected int max_width;            // The width of the widest line  protected int line_height;          // Total height of the font  protected int line_ascent;          // Font height above baseline  protected boolean measured = false; // Have the lines been measured?  // Here are five versions of the constructor  public MultiLineLabel(String label, int margin_width,                        int margin_height, int alignment) {    this.label = label;                 // Remember all the properties    this.margin_width = margin_width;    this.margin_height = margin_height;    this.alignment = alignment;    newLabel();                         // Break the label up into lines  }  public MultiLineLabel(String label, int margin_width, int margin_height) {    this(label, margin_width, margin_height, LEFT);  }  public MultiLineLabel(String label, int alignment) {    this(label, 10, 10, alignment);  }  public MultiLineLabel(String label) { this(label, 10, 10, LEFT); }  public MultiLineLabel() { this(""); }  // Methods to set and query the various attributes of the component  // Note that some query methods are inherited from the superclass.  public void setLabel(String label) {    this.label = label;    newLabel();               // Break the label into lines    measured = false;         // Note that we need to measure lines    repaint();                // Request a redraw  }  public void setFont(Font f) {    super.setFont(f);         // tell our superclass about the new font    measured = false;         // Note that we need to remeasure lines    repaint();                // Request a redraw  }  public void setForeground(Color c) {    super.setForeground(c);   // tell our superclass about the new color    repaint();                // Request a redraw (size is unchanged)  }  public void setAlignment(int a) { alignment = a; repaint(); }  public void setMarginWidth(int mw) { margin_width = mw; repaint(); }  public void setMarginHeight(int mh) { margin_height = mh; repaint(); }  public String getLabel() { return label; }  public int getAlignment() { return alignment; }  public int getMarginWidth() { return margin_width; }  public int getMarginHeight() { return margin_height; }  /**   * This method is called by a layout manager when it wants to   * know how big we'd like to be.  In Java 1.1, getPreferredSize() is   * the preferred version of this method.  We use this deprecated version   * so that this component can interoperate with 1.0 components.   */  public Dimension preferredSize() {    if (!measured) measure();    return new Dimension(max_width + 2*margin_width,                         num_lines * line_height + 2*margin_height);  }  /**   * This method is called when the layout manager wants to know   * the bare minimum amount of space we need to get by.   * For Java 1.1, we'd use getMinimumSize().   */  public Dimension minimumSize() { return preferredSize(); }  /**   * This method draws the label (same method that applets use).   * Note that it handles the margins and the alignment, but that   * it doesn't have to worry about the color or font--the superclass   * takes care of setting those in the Graphics object we're passed.   */  public void paint(Graphics g) {    int x, y;    Dimension size = this.size();  // use getSize() in Java 1.1    if (!measured) measure();    y = line_ascent + (size.height - num_lines * line_height)/2;    for(int i = 0; i < num_lines; i++, y += line_height) {      switch(alignment) {      default:      case LEFT:    x = margin_width; break;      case CENTER:  x = (size.width - line_widths[i])/2; break;      case RIGHT:   x = size.width - margin_width - line_widths[i]; break;      }      g.drawString(lines[i], x, y);    }  }  /** This internal method breaks a specified label up into an array of lines.   *  It uses the StringTokenizer utility class. */  protected synchronized void newLabel() {    StringTokenizer t = new StringTokenizer(label, "\n");    num_lines = t.countTokens();    lines = new String[num_lines];    line_widths = new int[num_lines];    for(int i = 0; i < num_lines; i++) lines[i] = t.nextToken();  }  /** This internal method figures out how the font is, and how wide each   *  line of the label is, and how wide the widest line is. */  protected synchronized void measure() {    FontMetrics fm = this.getToolkit().getFontMetrics(this.getFont());    line_height = fm.getHeight();    line_ascent = fm.getAscent();    max_width = 0;    for(int i = 0; i < num_lines; i++) {      line_widths[i] = fm.stringWidth(lines[i]);      if (line_widths[i] > max_width) max_width = line_widths[i];    }    measured = true;  }}	//	MultiLineLabel//////////		Code for the parser////////		// Mathematical expressions.// Copyright 1996 by Darius Bacon; see the file COPYING.// 14May96: added constant folding// 07JUL1999 - version 1.0 - C. Pheatt// 05AUG2001 - Mike May, S.J.//				add in SEC, CSC. ToDEG, TORAD, restore FACTpackage expr;/** * A mathematical expression, built out of literal numbers, variables, * arithmetic operators, and elementary functions.  The operator names * are from java.lang.Math. */public abstract class Expr {  /** @return the value given the current variable values */  public abstract double value ();  /** Binary operator. */  public static final int ADD = 0;    /** Binary operator. */  public static final int SUB = 1;  /** Binary operator. */  public static final int MUL = 2;  /** Binary operator. */  public static final int DIV = 3;  /** Binary operator. */  public static final int POW = 4;  /** Binary operator. */  public static final int MOD = 5;  /** Binary operator. */  public static final int LTH = 6;  /** Binary operator. */  public static final int LEQ = 7;  /** Binary operator. */  public static final int GTH = 8;  /** Binary operator. */  public static final int GEQ = 9;  /** Binary operator. */  public static final int EQU = 10;  /** Binary operator. */  public static final int NEQ = 11;  /** Binary operator. */  public static final int AND = 12;  /** Binary operator. */  public static final int ORR = 13;  /** Unary operator. */        public static final int ABS   = 100;  /** Unary operator. */        public static final int ACOS  = 101;  /** Unary operator. */        public static final int ASIN  = 102;  /** Unary operator. */        public static final int ATAN  = 103;  /** Unary operator. */        public static final int CEIL  = 104;  /** Unary operator. */        public static final int COS   = 105;  /** Unary operator. */        public static final int EXP   = 106;  /** Unary operator. */        public static final int FLOOR = 107;  /** Unary operator. */        public static final int LOG   = 108;  /** Unary minus operator. */  public static final int NEG   = 109;  /** Unary operator. */        public static final int ROUND = 110;  /** Unary operator. */        public static final int SIN   = 111;  /** Unary operator. */        public static final int SQRT  = 112;  /** Unary operator. */        public static final int TAN   = 113;  /** Unary operator. */        public static final int LOG10 = 114;  /** Unary operator. */        public static final int SEC   = 115;  /** Unary operator. */        public static final int CSC   = 116;  /** Unary operator. */        public static final int TODEG = 117;  /** Unary operator. */        public static final int TORAD = 118;  /** Unary operator. */     	public static final int FACT  = 119;    public static Expr make_literal (double v) {     return new Literal (v);   }  public static Expr make_var_ref (Variable var) {    return new Var_ref (var);  }  /**    * @param rator unary operator   * @param rand operand   */  public static Expr make_app1 (int rator, Expr rand) {    Expr app = new App1 (rator, rand);    return rand instanceof Literal ? new Literal (app.value ()) : app;  }  /**    * @param rator binary operator   * @param rand0 left operand   * @param rand1 right operand   */  public static Expr make_app2 (int rator, Expr rand0, Expr rand1) {    Expr app = new App2 (rator, rand0, rand1);    return rand0 instanceof Literal && rand1 instanceof Literal	     ? new Literal (app.value ()) 	     : app;  }}	//	Expr// These classes are all private to this module so that I can get rid// of them later.  For applets you want to use as few classes as// possible to avoid http connections at load time; it'd be profitable// to replace all these subtypes with bytecodes for a stack machine,// or perhaps a type that's the union of all of them (see class Node// in java/demo/SpreadSheet/SpreadSheet.java).class Literal extends Expr {  double v;  Literal (double _v) { v = _v; }  public double value () { return v; }}	//	Literalclass Var_ref extends Expr {  Variable var;  Var_ref (Variable _var) { var = _var; }  public double value () { return var.value (); }}	//	Var_refclass App1 extends Expr {  int rator;  Expr rand;  App1 (int _rator, Expr _rand) { rator = _rator; rand = _rand;  }  public double value () {    double arg = rand.value ();    switch (rator) {    case ABS:   return Math.abs (arg);    case ACOS:  return Math.acos (arg);    case ASIN:  return Math.asin (arg);    case ATAN:  return Math.atan (arg);    case CEIL:  return Math.ceil (arg);    case COS:   return Math.cos (arg);    case EXP:   return Math.exp (arg);    case FACT:  return MiscFunctions.fact (arg);    case FLOOR: return Math.floor (arg);    case LOG:   return Math.log (arg);    case LOG10: return Math.log (arg) * 0.434294481903251827651128918916;    case NEG:   return -arg;    case ROUND: return Math.round (arg);    case SIN:   return Math.sin (arg);    case SQRT:  return Math.sqrt (arg);    case TAN:   return Math.tan (arg);    case SEC:   return 1/Math.cos (arg);    case CSC:   return 1/Math.sin (arg);    case TODEG: return 180*(arg)/(3.141582653589793);    case TORAD: return (Math.PI)*(arg)/180;    default: throw new RuntimeException ("BUG: bad rator");    }  }}	//	App1class App2 extends Expr {  int rator;  Expr rand0, rand1;  App2 (int _rator, Expr _rand0, Expr _rand1) {     rator = _rator; rand0 = _rand0; rand1 = _rand1;  }  public double value () {    double arg0 = rand0.value ();    double arg1 = rand1.value ();    switch (rator) {    case ADD:  return arg0 + arg1;    case SUB:  return arg0 - arg1;    case MUL:  return arg0 * arg1;    case DIV:  return arg0 / arg1;   // check for division by 0?    case POW:  return Math.pow (arg0, arg1);    case MOD:  return arg0 % arg1;    case LTH:  if(arg0 < arg1) return 1; else return 0;    case LEQ:  if(arg0 <= arg1) return 1; else return 0;    case GTH:  if(arg0 > arg1) return 1; else return 0;    case GEQ:  if(arg0 >= arg1) return 1; else return 0;    case EQU:  if(arg0 == arg1) return 1; else return 0;    case NEQ:  if(arg0 != arg1) return 1; else return 0;    case AND:  if((arg0 != 0) && (arg1 != 0)) return 1; else return 0;    case ORR:  if((arg0 != 0) || (arg1 != 0)) return 1; else return 0;    default: throw new RuntimeException ("BUG: bad rator");    }  }}	//	App2//	End package Expr// Operator-precedence parser.// Copyright 1996 by Darius Bacon; see the file COPYING.// 14May96: bugfix. //	StreamTokenizer treated '-<number>' as a numeric token, not a minus//	operator followed by a number.  Fix: make '-' an ordinaryChar.// 12May97: Changed the precedence of unary minus to be lower than //      multiplication, so -y^2 is like -(y^2), not (-y)^2.// 07JUL1999 - version 1.0 - C. Pheatt// 05AUG2000 - Mike May, S.J.//				add in sec, csc, toDegrees, toRadians, ln, factpackage expr;import java.io.*;/**   Parses strings representing mathematical formulas with variables.  The following operators, in descending order of precedence, are  defined:  <UL>  <LI>^ (raise to a power)  <LI>* /  <LI>Unary minus (-x)  <LI>+ -  </UL>  ^ associates right-to-left; other operators associate left-to-right.  <P>These functions are defined:     abs, acos, asin, atan,     ceil, cos, exp, floor,     log, round, sin, sqrt,     tan.  Each requires one argument enclosed in parentheses.  <P>Whitespace outside identifiers is ignored.  <P>The syntax-error messages aren't very informative, unfortunately.  IWBNI it indicated where in the input string the parse failed, but   that'd be kind of a pain since our scanner is a StreamTokenizer.  A  hook for that info should've been built into StreamTokenizer.  <P>Examples:  <UL>  <LI>42  <LI>2-3  <LI>cos(x^2) + sin(x^2)  <UL> */public class Parser {  static StreamTokenizer tokens;  public static Expr parse (String input) throws Syntax_error {    tokens = new StreamTokenizer (new StringReader (input));    tokens.ordinaryChar ('/');    tokens.ordinaryChar ('-');    tokens.ordinaryChar ('%');    tokens.ordinaryChar ('>');    tokens.ordinaryChar ('<');    tokens.ordinaryChar ('=');    tokens.ordinaryChar ('!');    tokens.ordinaryChar ('&');    tokens.ordinaryChar ('|');    next ();    Expr expr = parse_expr (0);    if (tokens.ttype != StreamTokenizer.TT_EOF)      throw new Syntax_error ("Incomplete expression: " + input);    return expr;  }  static void next () {    try { tokens.nextToken (); }    catch (IOException e) { throw new RuntimeException ("I/O error: " + e); }  }  static void push () {     tokens.pushBack();   }  static void expect (int ttype) throws Syntax_error {    if (tokens.ttype != ttype)      throw new Syntax_error ("'" + (char) ttype + "' expected");    next ();  }  static Expr parse_expr (int precedence) throws Syntax_error {    Expr expr = parse_factor ();  loop: for (;;) {      int l, r, rator;         // The operator precedence table.      // l = left precedence, r = right precedence, rator = operator.      // Higher precedence values mean tighter binding of arguments.      // To associate left-to-right, let r = l+1;      // to associate right-to-left, let r = l.      switch (tokens.ttype) {      case '|':         l = 2; r = 3; rator = Expr.ORR;        next();        if(tokens.ttype != '|') push();        break;      case '&':         l = 4; r = 5; rator = Expr.AND;         next();        if(tokens.ttype != '&') push();        break;      case '=':         l = 6; r = 7; rator = Expr.EQU;         next();        if(tokens.ttype != '=') push();        break;              case '!':         l = 6; r = 7; rator = Expr.NEQ;         next();        if(tokens.ttype != '=') push();        break;            case '<':        l = 8; r = 9;        next();        if(tokens.ttype != '=')  {            push();            rator = Expr.LTH;         }        else {            rator = Expr.LEQ;         }            break;              case '>':        l = 8; r = 9;         next();        if(tokens.ttype != '=')  {            push();            rator = Expr.GTH;         }        else {            rator = Expr.GEQ;         }            break;            case '+': l = 10; r = 11; rator = Expr.ADD; break;      case '-': l = 10; r = 11; rator = Expr.SUB; break;	      case '%': l = 20; r = 21; rator = Expr.MOD; break;      case '*': l = 20; r = 21; rator = Expr.MUL; break;      case '/': l = 20; r = 21; rator = Expr.DIV; break;	      case '^': l = 30; r = 30; rator = Expr.POW; break; 	      default: break loop;      }      if (l < precedence)	break loop;      next ();      expr = Expr.make_app2 (rator, expr, parse_expr (r));    }    return expr;  }  static String[] procs = {    "abs", "acos","arccos", "asin",    "arcsin", "atan", "arctan",    "ceil", "cos", "exp", "floor",     "log", "ln", "round", "sin", "sqrt",     "tan", "log10", "sec", "csc",    "toDegrees", "toRadians", "fact"  };  static int[] rators = {    Expr.ABS, Expr.ACOS, Expr.ACOS, Expr.ASIN,    Expr.ASIN, Expr.ATAN, Expr.ATAN,     Expr.CEIL, Expr.COS, Expr.EXP, Expr.FLOOR,    Expr.LOG, Expr.LOG, Expr.ROUND, Expr.SIN, Expr.SQRT,     Expr.TAN , Expr.LOG10, Expr.SEC, Expr.CSC,    Expr.TODEG, Expr.TORAD, Expr.FACT  };	  static Expr parse_factor () throws Syntax_error {    switch (tokens.ttype) {    case StreamTokenizer.TT_NUMBER: {      Expr lit = Expr.make_literal (tokens.nval);      next ();      return lit;    }    case StreamTokenizer.TT_WORD: {      for (int i = 0; i < procs.length; ++i)	if (procs [i].equals (tokens.sval)) {	  next ();	  expect ('(');	  Expr rand = parse_expr (0);	  expect (')');	  return Expr.make_app1 (rators [i], rand);	}      Expr var = Expr.make_var_ref (Variable.make (tokens.sval));      next ();      return var;    }    case '(': {      next ();      Expr enclosed = parse_expr (0);      expect (')');      return enclosed;    }    case '-':       next ();      return Expr.make_app1 (Expr.NEG, parse_expr (15));    default:      throw new Syntax_error ("Expected a factor");    }  }}// Syntax-error exception.// Copyright 1996 by Darius Bacon; see the file COPYING.package expr;public class Syntax_error extends Exception {  public Syntax_error (String complaint) { super (complaint); }}// Put the expression evaluator through its paces.// Sample usage:// $ java expr.Test '3.14159 * x^2' 0 4 1// 0// 3.14159// 12.5664// 28.2743// 50.2654//// $ java expr.Test 'sin (pi/4 * x)' 0 4 1// 0// 0.707107// 1// 0.707107// 1.22461e-16//package expr;import expr.*;public class Test {  public static void main (String[] args) {    Expr expr;   	try   	{   		expr = Parser.parse (args [0]);   	}	catch (Syntax_error e)	{		System.err.println ("Syntax error: " + e);		return;	}    double low  = Double.valueOf (args [1]).doubleValue ();    double high = Double.valueOf (args [2]).doubleValue ();    double step = Double.valueOf (args [3]).doubleValue ();          Variable x = Variable.make ("x");    Variable.make ("pi").set_value (Math.PI);    for (double xval = low; xval <= high; xval += step) {      x.set_value (xval);      System.out.println (expr.value ());    }  }}/*	Trivial library - 4/96 PNL*/public class TrivialClass {		public TrivialClass() {	}}// Variables associate values with names.// Copyright 1996 by Darius Bacon; see the file COPYING.package expr;import java.util.Hashtable;/** * Variables associate values with names. */public class Variable {  static Hashtable variables = new Hashtable ();  /**   * Return <EM>the</EM> variable named `_name'.     * make (s1) == make (s2) iff s1.equals (s2).   */  static public Variable make (String _name) {    Variable result = (Variable) variables.get (_name);    if (result == null)      variables.put (_name, result = new Variable (_name));    return result;  }  String name;  double val;  public Variable (String _name) { name = _name; val = 5; }  public String toString () { return name; }  public double value () { return val; }  public void set_value (double _val) { val = _val; }}	//	Variable// mathGraph Utilitiespackage expr;import java.math.BigInteger;public class MiscFunctions {        public static double gamma(double parameter)    {        return Math.exp(gammln(parameter));    }    public static double fact(double n)    {	    double values[]={   1.0,                    1.0,                      2.0,                       6.0,	                       24.0,                  120.0,                    720.0,                    5040.0,	                    40320.0,               362880.0,                3628800.0,                39916800.0,	                479001600.0,           6227020800.0,            87178291200.0,           1307674368000.0,	           20922789888000.0,      355687428096000.0,       6402373705728000.0,      121645100408832000.0,	      2432902008176640000.0, 51090942171709440000.0, 1124000727777607680000.0, 25852016738884976640000.0	    };	    if(n < 0.0) return Double.NaN;		    if (n > 23 || (n != Math.round(n))) return Math.exp(gammln(n + 1.0));	    return values[(int)Math.round(n)];    }    static public BigInteger combinations(int N, int r) {  BigInteger ONE = new BigInteger("1");  if(r == 0) return ONE;    BigInteger denom = ONE;  BigInteger num = ONE;  BigInteger temp = new BigInteger(new String().valueOf(N));  int fact1 = N - r, fact2 = r;    if(r > (N-r)) {    fact1 = r;    fact2 = N - r;  }  for(int i = N; i > fact1; i--) {      num = num.multiply(temp);      temp = temp.subtract(ONE);  }   temp = ONE;  for(int i = 1; i <= fact2; i++) {      denom = denom.multiply(temp);      temp = temp.add(ONE);  }        return num.divide(denom);}    static public double beta(double z, double w) {    return Math.exp(gammln(z)+gammln(w)-gammln(z+w));}    static public double betai(double a, double b, double x){	double bt;	if (x < 0.0 || x > 1.0) return Double.NaN; // Bad x in routine betai	if (x == 0.0 || x == 1.0) bt=0.0;	else		bt=Math.exp(gammln(a+b)-gammln(a)-gammln(b)+a*Math.log(x)+b*Math.log(1.0-x));	if (x < (a+1.0)/(a+b+2.0))		return bt*betacf(a,b,x)/a;	else		return 1.0-bt*betacf(b,a,1.0-x)/b;}/* (C) Copr. 1986-92 Numerical Recipes Software *1%. */static public double betacf(double a, double b, double x) {	final int MAXIT=100;	final double EPS=3.0e-7, FPMIN=1.0e-30;		int m,m2;	double aa,c,d,del,h,qab,qam,qap;	qab=a+b;	qap=a+1.0;	qam=a-1.0;	c=1.0;	d=1.0-qab*x/qap;	if (Math.abs(d) < FPMIN) d=FPMIN;	d=1.0/d;	h=d;	for (m=1;m<=MAXIT;m++) {		m2=2*m;		aa=m*(b-m)*x/((qam+m2)*(a+m2));		d=1.0+aa*d;		if (Math.abs(d) < FPMIN) d=FPMIN;		c=1.0+aa/c;		if (Math.abs(c) < FPMIN) c=FPMIN;		d=1.0/d;		h *= d*c;		aa = -(a+m)*(qab+m)*x/((a+m2)*(qap+m2));		d=1.0+aa*d;		if (Math.abs(d) < FPMIN) d=FPMIN;		c=1.0+aa/c;		if (Math.abs(c) < FPMIN) c=FPMIN;		d=1.0/d;		del=d*c;		h *= del;		if (Math.abs(del-1.0) < EPS) break;	}	if (m > MAXIT) return Double.NaN; // a or b too big, or MAXIT too small in betacf	return h;}/* (C) Copr. 1986-92 Numerical Recipes Software *1%. */static public double gammln(double xx){	double x,y,tmp,ser;	final double[] cof ={76.18009172947146,-86.50532032941677,		24.01409824083091,-1.231739572450155,		0.1208650973866179e-2,-0.5395239384953e-5};	int j;	y=x=xx;	tmp=x+5.5;	tmp -= (x+0.5)*Math.log(tmp);	ser=1.000000000190015;	for (j=0;j<=5;j++) ser += cof[j]/++y;	return -tmp+Math.log(2.5066282746310005*ser/x);}/* (C) Copr. 1986-92 Numerical Recipes Software *1%. */    public java.lang.String toString()	{		return "MiscellaneousFunctions[" + 		        version + "]";	}    String version = "Version 1.0 - 07JUL1999";}/*  Copying file for expr packageCopyright 1996 by Darius Bacon.Permission is granted to anyone to use this software for anypurpose on any computer system, and to redistribute it freely,subject to the following restrictions:1. The author is not responsible for the consequences of use of   this software, no matter how awful, even if they arise from    defects in it.2. The origin of this software must not be misrepresented, either   by explicit claim or by omission.3. Altered versions must be plainly marked as such, and must not   be misrepresented as being the original software.   *///	MIO = My Input Output//	It is a collection of methods for cleaning up input and output.//	Mike May, S.J.//	maymk@slu.edu//	August, 2001/*	Current method list *	public static int intFromTextField(TextField tf)  *	public static double doubleFromTextField(TextField tf)  *	public static String doubleToStringDecPrecision(double d, int decfigs)  *	public static String doubleToStringNoE(TextField tf)  *	public static String doubleToStringSigFigures(double d, int sigfigs) * *	This version tries to interpret doubles first in Java format, then as *	an NFunction.  Java format allows sx.xxxxxxEsxxx while NFunctions *	allow usual mathematical constructions. */package MIO;import	java.awt.*;import	NFunction;public  class Mio {		public Mio() {}/** This is a utility routine to retrieve an integer from a text field. */	public static int intFromTextField(TextField tf) 	{		String  string;		int     value;				string = tf.getText();		try {		   value = Integer.parseInt(string);		} catch (Exception e) {       System.out.println("Warning, noninteger read for integer value.");       System.out.println("The variable has be set to 0.");		   value = 0;		}		   		return value;	}	//	intFromTextField	public static double doubleFromTextField(TextField tf) 	{		NFunction	func = new NFunction();   				String		string;		double		value;				string = tf.getText();		try {			value = Double.valueOf(string).doubleValue();		} catch (Exception e) {		try {		func.parse(string);			value = func.value(1);		} catch (Exception se) {       System.out.println("Warning, nondouble read for double value.");       System.out.println("The variable has be set to 0.0.");		   value = 0.0;		}}		return value;	}	//	doubleFromTextField	//	This procedure is intended to turn a double into a a string with a 	// specified decimal precision.	public static String doubleToStringDecPrecision(double d, int decfigs) 	{	     if (d == 0) return "0.0";	     else return String.valueOf((Math.round(d*(Math.pow(10,decfigs))))/                  (Math.pow(10,decfigs)));	}	//	doubleToStringDecPrecision	//	This procedure is intended to turn a double into a string with the added	//	provision being that the string not use E notation.	//	The point is if the string is then to be used in a an expression by a parser.	//	The output format is either (sxxx.xxx) or (sx.xxxx)*10^(sxxx).	public static String doubleToStringNoE(double d) 	{		String s1 = Double.toString(d);		int loc = s1.indexOf("E");		int len = s1.length();			System.out.println("E at " + loc + " length is " + len);		if (loc == -1) return s1;		else return "(" + s1.substring(0,loc) +")*10^(" + s1.substring(loc+1,len) + ")";	}	//	doubleToStringNoE	//	This procedure is intended to turn a double into a string with a specified	//	number of significant figures.  We need to divide into cases on whether	//	s1 is already in scientific notation.	public static String doubleToStringSigFigures(double d, int sigfigs)	{		String s1 = Double.toString(d);		int len = s1.length();		int loc = s1.indexOf("E");		int posdot = s1.indexOf(".");		int pos;		if (sigfigs < 1) return s1;		if (loc != -1)	// There is an E in s1		{			pos = Math.min(posdot+sigfigs, loc);				return  s1.substring(0,pos) +"E" + s1.substring(loc+1,len);		}		else	// no E in the string representation s1		{			pos = sigfigs + 1;			if (s1.indexOf("-") == 0) pos += 1;			if (posdot <= pos)	//	Need to keep figures right of decimal			{					int dotMove = (Double.toString(d*1000.0).indexOf(".") - posdot);				int leadZeroes = 3 - dotMove;	// count leading zeroes and adjust				if (leadZeroes > 0) pos += leadZeroes;				pos = Math.min(pos, len);				return s1.substring(0, pos);			}			int numZeroes = posdot - pos;			String s2 = s1.substring(0, pos);			for (int i = 0; i< numZeroes; i++) s2 = s2 + "0";			return s2 + ".0";		}	}	//	doubleToStringSigFigures}	//	class MIO