 /*
  * Khoros: $Id: function.c,v 1.1 1991/05/10 15:57:18 khoros Exp $
  */

#if !defined(lint) && !defined(SABER)
static char rcsid[] = "Khoros: $Id: function.c,v 1.1 1991/05/10 15:57:18 khoros Exp $";
#endif

 /*
  * $Log: function.c,v $
 * Revision 1.1  1991/05/10  15:57:18  khoros
 * Initial revision
 *
  */ 


/*
 *----------------------------------------------------------------------
 *
 * Copyright 1990, University of New Mexico.  All rights reserved.
 * Permission to copy and modify this software and its documen-
 * tation only for internal use in your organization is hereby
 * granted, provided that this notice is retained thereon and
 * on all copies.  UNM makes no representations as too the sui-
 * tability and operability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 * 
 * UNM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
 * NESS.  IN NO EVENT SHALL UNM BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY OTHER DAMAGES WHAT-
 * SOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PER-
 * FORMANCE OF THIS SOFTWARE.
 * 
 * No other rights, including for example, the right to redis-
 * tribute this software and its documentation or the right to
 * prepare derivative works, are granted unless specifically
 * provided in a separate license agreement.
 *---------------------------------------------------------------------
 */

#include "unmcopyright.h"	 /* Copyright 1990 by UNM */
#include "xprism.h"


/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
   >>>>                                                       <<<<
   >>>>	    file name: routines.c
   >>>>                                        
   >>>>   description: Utility routines to take the function
   >>>>			from the called, parse the function
   >>>>			and hand back an Xplot structure
   >>>>                                                
   >>>>      routines: 				
   >>>>			get_function
   >>>>			generate_plot
   >>>>			creat_plot
   >>>>                                      
   >>>> modifications:	
   >>>>                                                       <<<<
   >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */



/***********************************************************************
*
*  Routine Name: get_function
*
*          Date: unknown
*        
*       Purpose:  takes a function and intervals and parses the function
*		  and hands back an Xplot structure.
*
*         Input:  
*
*        Output: 
*
*    Written By:  
*
* Modifications:
*
***********************************************************************/


XPlot *get_function(plot_type, function, intv1, intv2, error)

int	plot_type;
char	*function, *intv1, *intv2, *error;
{
	Coord   *points;
	XPlot	*plot, *create_plot();
	float   xbeg, xend, xincr, ybeg, yend, yincr, xval, yval, value;

	char    temp[512];
	int	i, j, xsize, ysize;


	if (xve_eval_float(0, function, &value, error) == False)
	   return(NULL);

	if (! get_range(intv1, &xbeg, &xend, &xsize, error))
	   return(NULL);

	if (xend <= xbeg)
	{
	   sprintf(error,"get_function: Error, the beginning point is \
greater than the ending point. Please check the X-interval values");
	   return(NULL);
	}

	if (xsize > 1)
	   xincr = (xend - xbeg)/((float) (xsize - 1));
	else
	   xincr = (xend - xbeg);

	if (PLOT_TYPE_3D(plot_type))
	{
	   if (! get_range(intv2, &ybeg, &yend, &ysize, error))
		return(NULL);

	   if (xend <= xbeg)
	   {
	      sprintf(error,"get_function: Error, the beginning point is \
greater than the ending point. Please check the Y-interval values");
	      return(NULL);
	   }
	   if (ysize > 1)
	     yincr = (yend - ybeg)/((float) (ysize - 1));
	   else
	     yincr = (yend - ybeg);
	}
	else ysize = 1;
	
	if (xsize*ysize <= 0)
	{
	   sprintf(error,"get_function: Error, the number of data points \
specified is less than or equal to zero. Please specify the number of \
points to be greater than zero");
	   return(NULL);
	}

	plot = create_plot(plot_type, xsize*ysize, xsize, error);
	if (plot == NULL)
	   return(NULL);

	points = plot->points;

	if (PLOT_TYPE_2D(plot_type))
	{
	   for (i = 0; i < xsize; i++)
	   {
	      xval = i*xincr + xbeg;
	      sprintf(temp,"f(%g)", xval);
	      if (xve_eval_float(0, temp, &value, error) == False)
		 return(NULL);

	      points->y = value;
	      points->x = xval;
	      points++;
	   }
	}
	else
	{
	   for (j = 0; j < ysize; j++)
	   {
	      yval = j*yincr + ybeg;
	      for (i = 0; i < xsize; i++)
	      {
		 xval = i*xincr + xbeg;
	         sprintf(temp,"f(%g,%g)", xval, yval);
	         if (xve_eval_float(0, temp, &value, error) == False)
		    return(NULL);

	         points->z = value;
	         points->y = yval;
	         points->x = xval;
		 points++;
	      }
	   }
	}

	if (function != NULL)
	   plot->function = VStrcpy(function);
	else
	   plot->function = NULL;

	if (intv1 != NULL)
	   plot->xrange   = VStrcpy(intv1);
	else
	   plot->xrange   = NULL;

	if (intv2 != NULL)
	   plot->yrange   = VStrcpy(intv2);
	else
	   plot->yrange   = NULL;

	plot->begin_point.x =
	plot->begin_point.y =
	plot->end_point.x =
	plot->end_point.y = 0.0;
	plot->step_size.x =
	plot->step_size.y = 1.0;
	plot->machine_type_index = -1;
        plot->band = -1;
        plot->cmplx = -1;

	find_min_max (plot, plot_type);
	return(plot);
}



/***********************************************************************
*
*  Routine Name: create_plot
*
*          Date:
*        
*       Purpose:  
*
*         Input: 
*
*        Output: 
*
*    Written By:  
*
* Modifications:
*
***********************************************************************/

XPlot *create_plot(plot_type, size, row_size, error)

int	plot_type, size, row_size;
char	*error;
{
	XPlot *plot;

	if (!(plot = (XPlot *) malloc((unsigned) sizeof(XPlot))))
	{
	   sprintf(error,"create_plot: error\n not enough memory.\n");
	   return(NULL);
	}

	plot->plot_type  = plot_type;
	plot->input_type = KEYB_FUN;
	plot->data_type  = VFF_TYP_FLOAT;
	plot->size	 = size;
	plot->row_size	 = row_size;
	plot->filename   = NULL;
	plot->points	 = (Coord *) calloc(1, sizeof(Coord) * size);
	if (plot->points == NULL)
	{
	   sprintf(error,"create_plot: Error, not enough memory for %d \
data points.\n", size);
	   return(NULL);
	}
	return(plot);
}

/***********************************************************************
*
*  Routine Name: get_function
*
*          Date: unknown
*        
*       Purpose:  takes a function interval specification, parses it and
*		  hands back each part.
*
*         Input:  
*
*        Output: 
*
*    Written By:  Tom Sauer, Mark Young
*
* Modifications:
*
***********************************************************************/
int get_range(intv1, beg, end, size, error)

char *intv1, *error;
float *beg, *end;
int   *size;
{
	char	dummy[100], init[100], last[100], num_points[100]; 

	if (sscanf(intv1," %[^=]%*[ =\t\n](%[^,],%[^,],%[^)])", dummy,
				init, last, num_points) != 4)
	{
	   sprintf(error,"get_function:  Error, unable to parse interval \
string\n.  String is '%s'", intv1);
	   return(False);
	}

	if (xve_eval_float(0, init, beg, error) == False)
	   return(False);

	if (xve_eval_float(0, last, end, error) == False)
	   return(False);

	if (xve_eval_int(0, num_points, size, error) == False)
	   return(False);

	return(True);
}
