/*eval module, evaluates (atomizes) expressions */
#include <math.h>
#include <stdio.h>
#include "ana_structures.h"
#include "defs.h"
#define get_edb_ptr(ns) \
 narg = (int) sym[ns].type;\
 if (narg<5) ap= &sym[ns].spec.evb.args[0];\
 else ap = (unsigned short *) sym[ns].spec.array.ptr;
 extern	struct sym_desc sym[];
 extern	char *find_sym_name(int iq);
 extern	int	execute_error( int n );
 extern	int	temp_base;
 extern	int	num_ana_func;
 extern	int	ana_type_size[];
 extern	struct ana_subr_struct ana_func[]; 
 int	ana_add(void), ana_sub(void), ana_mul(void), ana_div(void),
	 ana_mod(void), ana_max(void), ana_min(void);
 int	ana_add_s_a(void), ana_sub_s_a(void), ana_mul_s_a(void),
	 ana_div_s_a(void), ana_max_s_a(void), ana_mod_s_a(void),
	 ana_min_s_a(void);
 int	ana_sub_a_s(void), ana_div_a_s(void) ,ana_mod_a_s(void);
 extern	int	ana_eq(), ana_eq_s_a(), ana_gt(), ana_gt_s_a();
 extern	int	ana_ge(), ana_ge_s_a(), ana_lt(), ana_lt_s_a();
 extern	int	ana_le(), ana_le_s_a(), ana_ne(), ana_ne_s_a();
 extern	int	ana_or(), ana_and(), ana_xor();
 extern	int	ana_or_s_a(), ana_and_s_a(), ana_xor_s_a();
 static	int	loop[10], inca[10], incb[10], lb[10];
/* 3/25/94  base needs to be an I*8, not an int, for 64 bit machines */
#ifdef __alpha 
 static	long	basea[10], baseb[10];
#ifdef __sgi
#if _MIPS_SZPTR == 64
 static	long	basea[10], baseb[10];
#endif
#endif
#else
 static	int	basea[10], baseb[10];
#endif
 /* note that folowing are also used in eval2.c */
 int	bsym1, bsym2;			/*symbol #'s for binary ops */
 int	result_sym;			/*output symbol */
 int	type1, type2, nelem;
 int	(*bin_ops[])()={
		 ana_add, ana_sub, ana_mul, ana_div, ana_mod, ana_max, ana_min,
		 ana_eq, ana_gt, ana_ge, ana_lt, ana_le, ana_ne,
		 ana_or, ana_and, ana_xor};
 int	(*bin_ops_s_a[])()={
		 ana_add_s_a, ana_sub_s_a, ana_mul_s_a, ana_div_s_a,
		 ana_mod_s_a, ana_max_s_a, ana_min_s_a,
		 ana_eq_s_a, ana_gt_s_a, ana_ge_s_a, ana_lt_s_a, ana_le_s_a,
		 ana_ne_s_a,
		 ana_or_s_a, ana_and_s_a, ana_xor_s_a};
 /*note that the array scalar binary op list uses the scalar/array calls
 for ops that commute and uses the reverse op in cases where order reversal
 is equivalent to a defined reverse op (such as LT == GT for reversed order)*/
 int	(*bin_ops_a_s[])()={
		 ana_add_s_a, ana_sub_a_s, ana_mul_s_a, ana_div_a_s,
		 ana_mod_a_s, ana_max_s_a, ana_min_s_a,
		 ana_eq_s_a, ana_lt_s_a, ana_le_s_a, ana_gt_s_a, ana_ge_s_a,
		 ana_ne_s_a,
		 ana_or_s_a, ana_and_s_a, ana_xor_s_a};
 union	types_ptr { byte *b; short *w; int *l; float *f; double *d;} p1,p2,p3;		
 /*------------------------------------------------------------------------- */
int	eval(nsym)
 /*re-entrant evaluation routine */
 unsigned int nsym;
 {
 int iq, narg, n;
 unsigned short	*ap;
 int	*apf, *arg_syms;
 /*printf("in eval, passed symbol # = %d\n",nsym);*/
 if (nsym < 0 ) return nsym;			/* pass errors through */
 /*check class */
 /*pass undefined's through 10/15/91 */
 iq = sym[nsym].class;
 /*if ( (iq = sym[nsym].class) == 255 )*/			/*defined ?*/
 /*	execute_error(7);*/				/*catch undefines */
 if ( iq < 192 )		{				/*evb or atom? */
	 switch (iq) {			/*atom case */
	 case 0:
	 	sym[nsym].class = 255;	/* make 0 into 255 */
	 case 1:
	 case 2:
	 case 4:
	 case 6:
	 case 7:
	 case 8:				/*pass 8's through also */
	 case SYM_PTR:				/*9's are handled by subsc */
	 case STRING_PTR:			/* string array, in subsc */
	 case SYM_ARR:				/* symbol array, in subsc */
	 case 255:
		 return nsym;
	 case 3:				/*compile string, resolve */
	 while (sym[nsym].class==3) {nsym = (unsigned int) sym[nsym].spec.evb.args[0]; }
	 return eval(nsym);
	 case 5:				/*ptrs to atoms, resolve */
	 while (sym[nsym].class==5) {nsym = (unsigned int) sym[nsym].spec.evb.args[0]; }
	 return eval(nsym);
	 default: 
	 printf("symbol # %d, class = %d\n", nsym, iq);
	 return execute_error(8);
 }
 }						/*end of atom cases */
 narg = (int) sym[nsym].type;
 if ( iq == 192 ) {				/*binary op evb */
 /*note that bsym1 and bsym2 are global, hence first eval result saved in
	 local iq before putting in bsym1 */
 iq    = eval( sym[nsym].spec.evb.args[1] );
 bsym2 = eval( sym[nsym].spec.evb.args[0] ); /*note order reversal */
 bsym1 = iq;
 iq = sym[nsym].xx;				/*this is the op # */
 if ( iq < 0 || iq > 15 )			/*a check, just in case */
	 { return execute_error(9); }
 /*we expect atomic arguments, divide into various combinations */
 switch ( sym[bsym1].class ) {
 case 8: bsym1 = class8_to_1( bsym1);
 case 1:
							 /*first a scalar */
  switch ( sym[bsym2].class ) {
   case 8: bsym2 = class8_to_1( bsym2);
   case 1: return  eval_scalars (iq);			/*both scalars */
	 /*first a scalar but not second, must be an array or illegal */
   case 4: return  eval_s_a (iq);
					 /*illegal if here, what was it ? */
   case 2: return execute_error(26);
   case 255: return execute_error(7);
   default:  return execute_error(27);
   }
 
 case 4:						/*first an array */
 
  switch ( sym[bsym2].class ) {
   case 4: return  eval_arrays (iq);			/*both arrays */
	 /*first an array but not second, must be a scalar or illegal */
   case 8: bsym2 = class8_to_1( bsym2);
   case 1:  return  eval_a_s (iq);
					 /*illegal if here, what was it ? */
   case 2: return execute_error(26);
   case 255: return execute_error(7);
   default:  return execute_error(27);
  }  
 
 case 2:						/*first a string */
	 /* second must be a string and only a few ops allowed */
   if ( sym[bsym2].class != 2 ) return execute_error(26);
   switch (iq) {
   case 0:	return  ana_string_add();
   case 7:	return	ana_string_eq();
   case 12:	return	ana_string_ne();
   default:	return execute_error(26);
   }
 case 255:	return execute_error(7);
 default:  return execute_error(27);
 }
 }						/*end of binary op evb */
 if ( iq == 193 ) {				/*non- binary evb */
	 /*need to check if internal or user function */
  if (sym[nsym].xx >= num_ana_func)  return (user_func_exec(nsym));
						 /* must be internal */
  get_edb_ptr(nsym)	/*a macro that gets narg and arg ptr */
  iq = sym[nsym].xx;	/* the function # */
			 /* check arg count against tabulated allowed values */
  if (narg < ana_func[iq].minargs || narg > ana_func[iq].maxargs)
	 return function_error(55, iq); 
  /* check for a subsc fn in case it needs to be redefined */
  if (iq == ANA_SUBSC_FUN) { /* check if target is defined */
   switch (sym[ *(ap+(narg-1))].class) {
    case 0:
    case 255:
    		return array_not_defined(nsym);
    } /* otherwise we just continue */
  }
  if (narg > 0 ) {
   ap = ap+(narg-1);
   n = narg;
 if ( (arg_syms = (int *) malloc( narg * sizeof (int) )) == NULL)
	 return execute_error(23);
 /*printf("malloc in eval, ptr = %d ****\n", arg_syms);*/
 apf = arg_syms;
 while (n--)	{	/*eval the arguments */
  *apf = eval ( *ap );
  apf++; ap--;}
						 /*call the function */
  n = (*ana_func[iq].ptr) (narg,arg_syms);
  /*printf("free in eval, ptr = %d ####\n",arg_syms);*/
  free ( arg_syms );	/*free input symbol list */
 } else {
  n = (*ana_func[iq].ptr) (0, &narg);
 }
 if (n < 0) return function_error(0,iq);
 return n;
 }						/*end of non-binary evb */
 return nsym;
 }
 /*------------------------------------------------------------------------- */
int	array_not_defined(unsigned int nsym)
 {
 int iq, narg, n;
 unsigned short	*ap, *apf, temp[4];
 char	*s;
 /* look again for the name in the function table, may have beem defined
	 in the meantime */
 get_edb_ptr(nsym)	/*a macro that gets narg and arg ptr */
 apf = ap+(narg-1);
 iq = (unsigned int) *apf;
 s = find_sym_name(iq);
 /*printf("re-checking for %s\n", s);*/
 if ((iq = find_fun(s)) <= 0 ) {
 /*printf("searching library files for function: %s\n", s );*/
 iq = sblib(s, 1);
 if (iq != 1)  return execute_error(31);
 /* now try again to find the function in the table */
 iq = find_fun(s);
 if (iq <= 0) {
 printf("found the file but function still not compiled, a mistake ?\n");
 return -1;
 }
 }
 /*printf("iq, num_ana_func = %d %d\n", iq, num_ana_func);*/
 if (iq < num_ana_func) return execute_error(3);
 /* must be a new user function, reconstruct the original symbol */
 narg--;
 sym[nsym].class=193;	sym[nsym].type=narg;	sym[nsym].xx=iq;
 /* we drop the last arg in the (backwards) list, not a problem unless
	 we had 5 and now have 4 */
 if (narg == 4) {
	 for (iq=0;iq<narg;iq++) temp[iq] = *ap++;
	 free(sym[nsym].spec.array.ptr);
	 for (iq=0;iq<narg;iq++) sym[nsym].spec.evb.args[iq] = temp[iq];
	 }
 return (user_func_exec(nsym));
 }
 /*------------------------------------------------------------------------- */
int	function_error(k, fn)
 /* notifies about an error in a function and identifies the name */
 int	k, fn;
 {
 if (k) execute_error(k);	/*print message if number passed */
 printf("*** error in function %s\n", ana_func[fn].name);
 return -1;
 }
 /*------------------------------------------------------------------------- */
int	class8_to_1(nsym)
 /*copy the value of a class 8 scalar into a class 1 temp */
 int	nsym;
 {
 int	i;
 i=find_next_temp();
 sym[i].class=1;	sym[i].type=sym[nsym].type;	sym[i].xx= -1;
 /* note, no hash code for these because no associated symbol string */
 switch (sym[i].type) {
 case 0: sym[i].spec.scalar.b= * (byte   *)sym[nsym].spec.array.ptr; break;
 case 1: sym[i].spec.scalar.w= * (short  *)sym[nsym].spec.array.ptr; break;
 case 2: sym[i].spec.scalar.l= * (int    *)sym[nsym].spec.array.ptr; break;
 case 3: sym[i].spec.scalar.f= * (float  *)sym[nsym].spec.array.ptr; break;
 case 4: sym[i].spec.scalar.d= * (double *)sym[nsym].spec.array.ptr; break;
 }
 /*printf("returned class 8 copy symbol # %d\n",i);*/
 return i;
 }
 /*------------------------------------------------------------------------- */
int	ana_string_add()
 {
 int	mq, nsym;
 union	types_ptr q1,q2;
			 /*get combined length, don't include the nulls */
 mq = sym[bsym1].spec.array.bstore + sym[bsym2].spec.array.bstore - 2;
 nsym = string_scratch(mq);			/*for resultant string */
 /*printf("nsym = %d\n",nsym);*/
 q2.b = (byte *) sym[nsym].spec.array.ptr;
 mq = sym[bsym1].spec.array.bstore - 1;
 q1.b = (byte *) sym[bsym1].spec.array.ptr;
 bcopy( (char *) q1.b, (char *) q2.b, mq); q2.b +=mq; 
 mq = sym[bsym2].spec.array.bstore - 1;
 q1.b = (byte *) sym[bsym2].spec.array.ptr;
 bcopy( (char *) q1.b, (char *) q2.b, mq); q2.b +=mq; *q2.b = 0; /*null end */
 return nsym; 
 }
 /*------------------------------------------------------------------------- */
int	ana_string_eq()
 {
 int	mq, iq, result_sym;
 char	*p1, *p2;
 result_sym = scalar_scratch(2);
 p1 = (char *) sym[bsym1].spec.array.ptr;
 p2 = (char *) sym[bsym2].spec.array.ptr;
 if (strcmp(p1, p2) == 0) iq =1; else iq =0;
 sym[result_sym].spec.scalar.l = iq;
 return result_sym; 
 }
 /*------------------------------------------------------------------------- */
int	ana_string_ne()
 {
 int	mq, iq, result_sym;
 char	*p1, *p2;
 result_sym = scalar_scratch(2);
 p1 = (char *) sym[bsym1].spec.array.ptr;
 p2 = (char *) sym[bsym2].spec.array.ptr;
 if (strcmp(p1, p2) == 0) iq =0; else iq =1;
 sym[result_sym].spec.scalar.l = iq;
 return result_sym; 
 }
 /*------------------------------------------------------------------------- */
int	eval_scalars(iq)
 /*2 scalar case, iq is the op */
 int	iq;
 {
 int	top_type;
 if (sym[bsym1].type > sym[bsym2].type)
	 { top_type = sym[bsym1].type; }
	 else
	 { top_type = sym[bsym2].type; }
 type1 = sym[bsym1].type;
 type2 = sym[bsym2].type;
 /*result symbol type is op dependent */
 if (iq > 6 ) {	if (iq < 13 ) {				/*relational op */
		 /*these always have a long word result (which is 0 or 1) */
 top_type = 2;
 } else {						/*logical op */
 if (top_type > 2 ) return execute_error(29);		/*can't use floats */
 }}
 /*need an output symbol, anybody already a temp ? */
 if ( bsym1 >= temp_base ) { result_sym = bsym1;
		 sym[result_sym].type = top_type; }
	 else if ( bsym2 >= temp_base )  { result_sym = bsym2;
		 sym[result_sym].type = top_type; }
	 else result_sym = scalar_scratch(top_type);
 p1.l = &sym[bsym1].spec.scalar.l;
 p2.l = &sym[bsym2].spec.scalar.l;
 p3.l = &sym[result_sym].spec.scalar.l;
 nelem=1;
 return (*bin_ops[iq])();			/*call appropiate func */
 }						/*end of eval_scalars */
 /*------------------------------------------------------------------------- */
int	eval_arrays(iq)
 /*2 array case, iq is the op */
 /*7/7/91 r. shine */
 int	iq;
 {
 int	top_type, n, nd, nd2, j, top_sym, match, i;
 int	stride1, stride2;
 struct	ahead	*h, *h2;
 /*check dimension structures, if they match then a simple element by element
	 op; otherwise some special possibilities */
 match = 1;		/* assume match and zero if not */
 h = (struct ahead *) sym[bsym1].spec.array.ptr;
 p1.l = (int *) ((char *)h + sizeof(struct ahead));
 nd = h->ndim;
 nelem = 1; for (j=0;j<nd;j++) nelem *= h->dims[j];/*# of elements for bsym1 */
 h2 = (struct ahead *) sym[bsym2].spec.array.ptr;
 p2.l = (int *) ((char *)h2 + sizeof(struct ahead));
 nd2 = h2->ndim;
 /* printf("eval_arrays, p1.l, p2.l = %lx %lx\n", p1.l, p2.l); */
 n = 1; for (j=0;j<nd2;j++) n *= h2->dims[j];	/*# of elements for bsym2 */
 /* if the number of dimensions don't match, then can't have a scalarized
	 dimension but still do op element by element if totals match */
 if ( nd != nd2 ) { if ( n != nelem ) return execute_error(24); } else {
 /* we now know that n dim matches but need to check each one */
 for (j=0;j<nd;j++) if (h->dims[j] != h2->dims[j]) { match = 0; break; }
 }
 /* before further checking on match situation, do the types */
 type1 = sym[bsym1].type;
 type2 = sym[bsym2].type;
 if (type1 > type2)
	 { top_type = type1; top_sym = bsym1; }
	 else
	 { top_type = type2; top_sym = bsym2; }
 /*result symbol type is op dependent */
 if (iq > 6 ) {	if (iq < 13 ) {				/*relational op */
		 /*these always have a long word result (which is 0 or 1) */
 top_type = 2;
 } else {						/*logical op */
 if (top_type > 2 ) return execute_error(29);		/*can't use floats */
 }}
 /* action now depends on the match situation */
 switch (match) {
 case 1:		/*normal, element by element */
 /*need an output symbol, anybody already a temp of the right type ? */
 if ( bsym1 >= temp_base && sym[bsym1].type == top_type )
		 { result_sym = bsym1; p3.l = p1.l;
		 sym[result_sym].type = top_type; }
	 else if ( bsym2 >= temp_base && sym[bsym2].type == top_type )  
	 { result_sym = bsym2; p3.l = p2.l;
		 sym[result_sym].type = top_type; }
	 else { result_sym = array_clone(top_sym,top_type);
	 h = (struct ahead *) sym[result_sym].spec.array.ptr;
	 p3.l = (int *) ((char *)h + sizeof(struct ahead));
	  }
 return (*bin_ops[iq])();			/*call appropiate func */
 
 case 0:		/*dimension mismatch, candidate for scalarized dim */
 stride1 =  ana_type_size[type1]; 	stride2 = ana_type_size[type2];
 basea[0] = (long) p1.l;		baseb[0] = (long) p2.l;
 for (j=0;j<nd;j++) {
	 inca[j] = stride1;	stride1 *= h->dims[j];
	 incb[j] = stride2;	stride2 *= h2->dims[j];
	 if ( h->dims[j] != h2->dims[j] ) {
					 /* check if legal, one must be 1 */
	  if (h->dims[j] != 1 && h2->dims[j] != 1) return execute_error(24);
	  if (h->dims[j] == 1) inca[j] = 0; else incb[j] = 0;
	 }
	 loop[j] = lb[j] = MAX( h->dims[j], h2->dims[j] );
 }
 /* zero next loop, this is stop condition; n is inc for result array */
 loop[nd] = lb[nd] = 0;	n = lb[0] * ana_type_size[top_type];
 /*trickle up base */
 for (j=1;j<=nd;j++) { basea[j] = basea[0];  baseb[j] = baseb[0]; }
 result_sym = array_scratch(top_type, nd, loop); /* may not be same as either*/
 h = (struct ahead *) sym[result_sym].spec.array.ptr;
 p3.l = (int *) ((char *)h + sizeof(struct ahead));
 /* if we have a trivial inner loop for one of the arrays, a s/a or a/s series
	 is needed, otherwise a/a series */
 if ( inca[0] > 0 && incb[0] > 0 ) {			/* inner a/a case */
 nelem = lb[0];
 /*outer loops */
 while (1) { p1.l = (int *) basea[1];	p2.l = (int *) baseb[1];
 /* inner loop is call to appropiate binary op */
 ( *bin_ops[iq] )( );
 i = 1;
 /*process outer counts */
	 while (1) { loop[i] -= 1;
	 if ( loop[i] > 0 ) break;
	 if (loop[i] < 0) return result_sym;
	 i++; }
 basea[i] += inca[i];	baseb[i] += incb[i];
 while (i > 1)
   { i--; basea[i] = basea[i+1]; baseb[i] = baseb[i+1]; loop[i] = lb[i]; }
 p3.b += n;	}				/*end of outer loop while */
 } else {						/* inner scalar */
					 /* who is the scalar ? */
 if ( inca[0] == 0 ) {			/* s/a subcase */
 nelem = lb[0];
 /*outer loops */
 while (1) { p1.l = (int *) basea[1];	p2.l = (int *) baseb[1];
 /* inner loop is call to appropiate binary op */
 (*bin_ops_s_a[iq])();
 i = 1;
 /*process outer counts */
	 while (1) { loop[i] -= 1;
	 if ( loop[i] > 0 ) break;
	 if (loop[i] < 0) return result_sym;
	 i++; }
 basea[i] += inca[i];	baseb[i] += incb[i];
 while (i > 1)
   { i--; basea[i] = basea[i+1]; baseb[i] = baseb[i+1]; loop[i] = lb[i]; }
 p3.b += n;	}				/*end of outer loop while */
 
 } else {				/* a/s subcase */
 nelem = lb[0];
 /* note reverse identities for p1 and p2 for this case */
 i = type1;  type1 = type2;  type2 = i;
 /*outer loops */
 while (1) { p1.l = (int *) baseb[1];	p2.l = (int *) basea[1];
 /* inner loop is call to appropiate binary op */
 (*bin_ops_a_s[iq])();
 i = 1;
 /*process outer counts */
	 while (1) { loop[i] -= 1;
	 if ( loop[i] > 0 ) break;
	 if (loop[i] < 0) return result_sym;
	 i++; }
 basea[i] += inca[i];	baseb[i] += incb[i];
 while (i > 1)
   { i--; basea[i] = basea[i+1]; baseb[i] = baseb[i+1]; loop[i] = lb[i]; }
 p3.b += n;	}				/*end of outer loop while */
 
 }
 }
 }
 }						/*end of eval_arrays */
 /*------------------------------------------------------------------------- */
int	eval_s_a (iq)
 /*scalar / array case, iq is the op */
 /*7/9/91 r. shine */
 int	iq;
 {
 int	top_type,n,nd,j,top_sym;
 struct	ahead	*h;
						 /*first is the scalar */
 p1.l = &sym[bsym1].spec.scalar.l;
						 /*second is the array */
 h = (struct ahead *) sym[bsym2].spec.array.ptr;
 p2.l = (int *) ((char *)h + sizeof(struct ahead));
 nd = h->ndim;
 nelem = 1; for (j=0;j<nd;j++) nelem *= h->dims[j];/*# of elements for bsym1 */
 type1 = sym[bsym1].type;			/*the scalar type */
 type2 = sym[bsym2].type;			/*the array type */
 if (type1 > type2)			/*get top type */
	 { top_type = type1; }
	 else
	 { top_type = type2; }
 /*result symbol type is op dependent */
 if (iq > 6 ) {	if (iq < 13 ) {				/*relational op */
		 /*these always have a long word result (which is 0 or 1) */
 top_type = 2;
 } else {						/*logical op */
 if (top_type > 2 ) return execute_error(29);		/*can't use floats */
 }}
 /*need an output symbol, use array if a temp and top_type*/
 if ( bsym2 >= temp_base && sym[bsym2].type == top_type )
		 { result_sym = bsym2; p3.l = p2.l; }
	 else { result_sym = array_clone(bsym2,top_type);
	 h = (struct ahead *) sym[result_sym].spec.array.ptr;
	 p3.l = (int *) ((char *)h + sizeof(struct ahead));
	 }
 return (*bin_ops_s_a[iq])();			/*call appropiate func */
 }						/*end of eval_s_a */
 /*------------------------------------------------------------------------- */
int	eval_a_s (iq)
 /*array/scalar case, iq is the op */
 /*in order to reduce # of binary op routines, this case reverses the symbol
 order and uses appropiate scalar/array functions when possible, the
 bin_ops_a_s list is arranged to have the appropiate call, some (like subtract
 and divide) are unique to this list */
 /*7/10/91 r. shine */
 int	iq;
 {
 int	top_type,n,nd,j,top_sym;
 struct	ahead	*h;
						 /*reverse the symbol order */
 j = bsym1; bsym1 = bsym2; bsym2 = j;
						 /*bsym1 is now the scalar */
 p1.l = &sym[bsym1].spec.scalar.l;
						 /*bsym2 is the array */
 h = (struct ahead *) sym[bsym2].spec.array.ptr;
 p2.l = (int *) ((char *)h + sizeof(struct ahead));
 nd = h->ndim;
 nelem = 1; for (j=0;j<nd;j++) nelem *= h->dims[j];/*# of elements for bsym1 */
 type1 = sym[bsym1].type;			/*the scalar type */
 type2 = sym[bsym2].type;			/*the array type */
 if (type1 > type2)			/*get top type */
	 { top_type = type1; }
	 else
	 { top_type = type2; }
 /*result symbol type is op dependent */
 if (iq > 6 ) {	if (iq < 13 ) {				/*relational op */
		 /*these always have a long word result (which is 0 or 1) */
 top_type = 2;
 } else {						/*logical op */
 if (top_type > 2 ) return execute_error(29);	/*can't use floats */
 }}
 /*need an output symbol, use array if a temp and top_type*/
 if ( bsym2 >= temp_base && sym[bsym2].type == top_type )
		 { result_sym = bsym2; p3.l = p2.l; }
	 else { result_sym = array_clone(bsym2,top_type);
	 h = (struct ahead *) sym[result_sym].spec.array.ptr;
	 p3.l = (int *) ((char *)h + sizeof(struct ahead));
	  }
 return (*bin_ops_a_s[iq])();			/*call appropiate func */
 }						/*end of eval_s_a */
 /*------------------------------------------------------------------------- */
int	ana_add()
 /*add 2 symbols */
 {
 register union	types_ptr q1,q2,q3;
 register int n;
 q1.l = p1.l;	q2.l = p2.l;	q3.l = p3.l;	n = nelem;
 switch (type1)	{
 case 3:	switch (type2)	{
  case 3: while (n) {*q3.f++ =(*q1.f++)+(*q2.f++);n--; }break;
  case 2: while (n) {*q3.f++ =(*q1.f++)+(float)(*q2.l++);n--;}break;
  case 1: while (n) {*q3.f++ =(*q1.f++)+(float)(*q2.w++);n--;}break;
  case 0: while (n) {*q3.f++ =(*q1.f++)+(float)(*q2.b++);n--;}break;
  case 4: while (n) {*q3.d++ =(double)(*q1.f++)+(*q2.d++);n--;}break;
 }	break;
 case 2:	switch (type2)	{
  case 2: while (n) {*q3.l++ =(*q1.l++)+(*q2.l++);n--;}break;
  case 3: while (n) {*q3.f++ =(float)(*q1.l++)+(*q2.f++);n--;}break;
  case 1: while (n) {*q3.l++ =(*q1.l++)+(int)(*q2.w++);n--;}break;
  case 0: while (n) {*q3.l++ =(*q1.l++)+(int)(*q2.b++);n--;}break;
  case 4: while (n) {*q3.d++ =(double)(*q1.l++)+(*q2.d++);n--;}break;
 }	break;
 case 1:	switch (type2)	{
  case 1: while (n) {*q3.w++ =(*q1.w++)+(*q2.w++);n--;}break;
  case 3: while (n) {*q3.f++ =(float)(*q1.w++)+(*q2.f++);n--;}break;
  case 2: while (n) {*q3.l++ =(int)(*q1.w++)+(*q2.l++);n--;}break;
  case 0: while (n) {*q3.w++ =(*q1.w++)+(short)(*q2.b++);n--;}break;
  case 4: while (n) {*q3.d++ =(double)(*q1.w++)+(*q2.d++);n--;}break;
 }	break;
 case 0:	switch (type2)	{
  case 0: while (n) {*q3.b++ =(*q1.b++)+(*q2.b++);n--;}break;
  case 1: while (n) {*q3.w++ =(short)(*q1.b++)+(*q2.w++);n--;}break;
  case 3: while (n) {*q3.f++ =(float)(*q1.b++)+(*q2.f++);n--;}break;
  case 2: while (n) {*q3.l++ =(int)(*q1.b++)+(*q2.l++);n--;}break;
  case 4: while (n) {*q3.d++ =(double)(*q1.b++)+(*q2.d++);n--;}break;
 }	break;
 case 4:	switch (type2)	{
  case 4: while (n) {*q3.d++ =(*q1.d++)+(*q2.d++);n--;}break;
  case 3: while (n) {*q3.d++ =(*q1.d++)+(double)(*q2.f++);n--;}break;
  case 0: while (n) {*q3.d++ =(*q1.d++)+(double)(*q2.b++);n--;}break;
  case 1: while (n) {*q3.d++ =(*q1.d++)+(double)(*q2.w++);n--;}break;
  case 2: while (n) {*q3.d++ =(*q1.d++)+(double)(*q2.l++);n--;}break;
 }	break;
 }
 return result_sym;
 }
 /*------------------------------------------------------------------------- */
int	ana_add_s_a()
 /*add 2 symbols, first a scalar, second an array */
 {
 register union	types_ptr q2,q3;
 register union	scalar x;
 register int n;
 q2.l = p2.l;	q3.l = p3.l;	n = nelem;
 switch (type1)	{
 case 3:  x.f = *p1.f;
  switch (type2)	{
  case 3: while (n) {*q3.f++ =(x.f)+(*q2.f++);n--; }break;
  case 2: while (n) {*q3.f++ =(x.f)+(float)(*q2.l++);n--;}break;
  case 1: while (n) {*q3.f++ =(x.f)+(float)(*q2.w++);n--;}break;
  case 0: while (n) {*q3.f++ =(x.f)+(float)(*q2.b++);n--;}break;
  case 4: x.d = (double) x.f; 
	 while (n) {*q3.d++ =(x.d)+(*q2.d++);n--;}break;
 }	break;
 case 2:	
 /* printf("*p1.l = %d, p1.l = %lx, n = %d\n", *p1.l, p1.l, n); */
 x.l = *p1.l;
 /* printf("q3.l, q2.l %lx %lx\n", q3.l, q2.l); */
  switch (type2)	{
  case 2: while (n) {*q3.l++ =(x.l)+(*q2.l++);n--;}break;
  case 3: x.f=(float)(x.l); while (n) {*q3.f++ =(x.f)+(*q2.f++);n--;}break;
  case 1: while (n) {*q3.l++ =(x.l)+(int)(*q2.w++);n--;}break;
  case 0: while (n) {*q3.l++ =(x.l)+(int)(*q2.b++);n--;}break;
  case 4: x.d=(double)(x.l); while (n) {*q3.d++ =(x.d)+(*q2.d++);n--;}break;
 }	break;
 case 1:	 x.w = *p1.w;
  switch (type2)	{
  case 1: while (n) {*q3.w++ =(x.w)+(*q2.w++);n--;}break;
  case 3: x.f=(float)x.w; while (n) {*q3.f++ =(x.f)+(*q2.f++);n--;}break;
  case 2: x.l=(int)x.w; while (n) {*q3.l++ =(x.l)+(*q2.l++);n--;}break;
  case 0: while (n) {*q3.w++ =(x.w)+(short)(*q2.b++);n--;}break;
  case 4: x.d=(double)x.w; while (n) {*q3.d++ =(x.d)+(*q2.d++);n--;}break;
 }	break;
 case 0:	 x.b = *p1.b;
  switch (type2)	{
  case 0: while (n) {*q3.b++ =(x.b)+(*q2.b++);n--;}break;
  case 1: x.w=(short)x.b; while (n) {*q3.w++ =(x.w)+(*q2.w++);n--;}break;
  case 3: x.f=(float)x.b; while (n) {*q3.f++ =(x.f)+(*q2.f++);n--;}break;
  case 2: x.l=(int)x.b; while (n) {*q3.l++ =(x.l)+(*q2.l++);n--;}break;
  case 4: x.d=(double)x.b; while (n) {*q3.d++ =(x.d)+(*q2.d++);n--;}break;
 }	break;
 case 4:  x.d = *p1.d;	
  switch (type2)	{
  case 4: while (n) {*q3.d++ =(x.d)+(*q2.d++);n--;}break;
  case 3: while (n) {*q3.d++ =(x.d)+(double)(*q2.f++);n--;}break;
  case 0: while (n) {*q3.d++ =(x.d)+(double)(*q2.b++);n--;}break;
  case 1: while (n) {*q3.d++ =(x.d)+(double)(*q2.w++);n--;}break;
  case 2: while (n) {*q3.d++ =(x.d)+(double)(*q2.l++);n--;}break;
 }	break;
 }
 return result_sym;
 }
 /*------------------------------------------------------------------------- */
int	ana_sub()
 /*subtract 2 symbols */
 {
 register union	types_ptr q1,q2,q3;
 register int n;
 q1.l = p1.l;	q2.l = p2.l;	q3.l = p3.l;	n = nelem;
 switch (type1)	{
 case 3:	switch (type2)	{
  case 3: while (n) {*q3.f++ =(*q1.f++)-(*q2.f++);n--;
  }break;
  case 2: while (n) {*q3.f++ =(*q1.f++)-(float)(*q2.l++);n--;}break;
  case 1: while (n) {*q3.f++ =(*q1.f++)-(float)(*q2.w++);n--;}break;
  case 0: while (n) {*q3.f++ =(*q1.f++)-(float)(*q2.b++);n--;}break;
  case 4: while (n) {*q3.d++ =(double)(*q1.f++)-(*q2.d++);n--;}break;
 }	break;
 case 2:	switch (type2)	{
  case 2: while (n) {*q3.l++ =(*q1.l++)-(*q2.l++);n--;}break;
  case 3: while (n) {*q3.f++ =(float)(*q1.l++)-(*q2.f++);n--;}break;
  case 1: while (n) {*q3.l++ =(*q1.l++)-(int)(*q2.w++);n--;}break;
  case 0: while (n) {*q3.l++ =(*q1.l++)-(int)(*q2.b++);n--;}break;
  case 4: while (n) {*q3.d++ =(double)(*q1.l++)-(*q2.d++);n--;}break;
 }	break;
 case 1:	switch (type2)	{
  case 1: while (n) {*q3.w++ =(*q1.w++)-(*q2.w++);n--;}break;
  case 3: while (n) {*q3.f++ =(float)(*q1.w++)-(*q2.f++);n--;}break;
  case 2: while (n) {*q3.l++ =(int)(*q1.w++)-(*q2.l++);n--;}break;
  case 0: while (n) {*q3.w++ =(*q1.w++)-(short)(*q2.b++);n--;}break;
  case 4: while (n) {*q3.d++ =(double)(*q1.w++)-(*q2.d++);n--;}break;
 }	break;
 case 0:	switch (type2)	{
  case 0: while (n) {*q3.b++ =(*q1.b++)-(*q2.b++);n--;}break;
  case 1: while (n) {*q3.w++ =(short)(*q1.b++)-(*q2.w++);n--;}break;
  case 3: while (n) {*q3.f++ =(float)(*q1.b++)-(*q2.f++);n--;}break;
  case 2: while (n) {*q3.l++ =(int)(*q1.b++)-(*q2.l++);n--;}break;
  case 4: while (n) {*q3.d++ =(double)(*q1.b++)-(*q2.d++);n--;}break;
 }	break;
 case 4:	switch (type2)	{
  case 4: while (n) {*q3.d++ =(*q1.d++)-(*q2.d++);n--;}break;
  case 3: while (n) {*q3.d++ =(*q1.d++)-(double)(*q2.f++);n--;}break;
  case 0: while (n) {*q3.d++ =(*q1.d++)-(double)(*q2.b++);n--;}break;
  case 1: while (n) {*q3.d++ =(*q1.d++)-(double)(*q2.w++);n--;}break;
  case 2: while (n) {*q3.d++ =(*q1.d++)-(double)(*q2.l++);n--;}break;
 }	break;
 }
 return result_sym;
 }
 /*------------------------------------------------------------------------- */
int	ana_sub_s_a()
 /*sub2 symbols, first a scalar, second an array */
 {
 register union	types_ptr q2,q3;
 register union	scalar x;
 register int n;
 q2.l = p2.l;	q3.l = p3.l;	n = nelem;
 switch (type1)	{
 case 3:  x.f = *p1.f;
  switch (type2)	{
  case 3: while (n) {*q3.f++ =(x.f)-(*q2.f++);n--; }break;
  case 2: while (n) {*q3.f++ =(x.f)-(float)(*q2.l++);n--;}break;
  case 1: while (n) {*q3.f++ =(x.f)-(float)(*q2.w++);n--;}break;
  case 0: while (n) {*q3.f++ =(x.f)-(float)(*q2.b++);n--;}break;
  case 4: x.d = (double) x.f; 
	 while (n) {*q3.d++ =(x.d)-(*q2.d++);n--;}break;
 }	break;
 case 2:	 x.l = *p1.l;
  switch (type2)	{
  case 2: while (n) {*q3.l++ =(x.l)-(*q2.l++);n--;}break;
  case 3: x.f=(float)(x.l); while (n) {*q3.f++ =(x.f)-(*q2.f++);n--;}break;
  case 1: while (n) {*q3.l++ =(x.l)-(int)(*q2.w++);n--;}break;
  case 0: while (n) {*q3.l++ =(x.l)-(int)(*q2.b++);n--;}break;
  case 4: x.d=(double)(x.l); while (n) {*q3.d++ =(x.d)-(*q2.d++);n--;}break;
 }	break;
 case 1:	 x.w = *p1.w;
  switch (type2)	{
  case 1: while (n) {*q3.w++ =(x.w)-(*q2.w++);n--;}break;
  case 3: x.f=(float)x.w; while (n) {*q3.f++ =(x.f)-(*q2.f++);n--;}break;
  case 2: x.l=(int)x.w; while (n) {*q3.l++ =(x.l)-(*q2.l++);n--;}break;
  case 0: while (n) {*q3.w++ =(x.w)-(short)(*q2.b++);n--;}break;
  case 4: x.d=(double)x.w; while (n) {*q3.d++ =(x.d)-(*q2.d++);n--;}break;
 }	break;
 case 0:	 x.b = *p1.b;
  switch (type2)	{
  case 0: while (n) {*q3.b++ =(x.b)-(*q2.b++);n--;}break;
  case 1: x.w=(short)x.b; while (n) {*q3.w++ =(x.w)-(*q2.w++);n--;}break;
  case 3: x.f=(float)x.b; while (n) {*q3.f++ =(x.f)-(*q2.f++);n--;}break;
  case 2: x.l=(int)x.b; while (n) {*q3.l++ =(x.l)-(*q2.l++);n--;}break;
  case 4: x.d=(double)x.b; while (n) {*q3.d++ =(x.d)-(*q2.d++);n--;}break;
 }	break;
 case 4:  x.d = *p1.d;	
  switch (type2)	{
  case 4: while (n) {*q3.d++ =(x.d)-(*q2.d++);n--;}break;
  case 3: while (n) {*q3.d++ =(x.d)-(double)(*q2.f++);n--;}break;
  case 0: while (n) {*q3.d++ =(x.d)-(double)(*q2.b++);n--;}break;
  case 1: while (n) {*q3.d++ =(x.d)-(double)(*q2.w++);n--;}break;
  case 2: while (n) {*q3.d++ =(x.d)-(double)(*q2.l++);n--;}break;
 }	break;
 }
 return result_sym;
 }
 /*------------------------------------------------------------------------- */
int	ana_sub_a_s()
 /*sub 2 symbols, for original array/scalar case, symbol #'s were reversed */
 {
 register union	types_ptr q2,q3;
 register union	scalar x;
 register int n;
 q2.l = p2.l;	q3.l = p3.l;	n = nelem;
 switch (type1)	{
 case 3:  x.f = *p1.f;
  switch (type2)	{
  case 3: while (n) {*q3.f++ =(*q2.f++)-(x.f);n--; }break;
  case 2: while (n) {*q3.f++ =(float)(*q2.l++)-(x.f);n--;}break;
  case 1: while (n) {*q3.f++ =(float)(*q2.w++)-(x.f);n--;}break;
  case 0: while (n) {*q3.f++ =(float)(*q2.b++)-(x.f);n--;}break;
  case 4: x.d = (double) x.f; 
	 while (n) {*q3.d++ =(*q2.d++)-(x.d);n--;}break;
 }	break;
 case 2:	 x.l = *p1.l;
  switch (type2)	{
  case 2: while (n) {*q3.l++ =(*q2.l++)-(x.l);n--;}break;
  case 3: x.f=(float)(x.l); while (n) {*q3.f++ =(*q2.f++)-(x.f);n--;}break;
  case 1: while (n) {*q3.l++ =(int)(*q2.w++)-(x.l);n--;}break;
  case 0: while (n) {*q3.l++ =(int)(*q2.b++)-(x.l);n--;}break;
  case 4: x.d=(double)(x.l); while (n) {*q3.d++ =(*q2.d++)-(x.d);n--;}break;
 }	break;
 case 1:	 x.w = *p1.w;
  switch (type2)	{
  case 1: while (n) {*q3.w++ =(*q2.w++)-(x.w);n--;}break;
  case 3: x.f=(float)x.w; while (n) {*q3.f++ =(*q2.f++)-(x.f);n--;}break;
  case 2: x.l=(int)x.w; while (n) {*q3.l++ =(*q2.l++)-(x.l);n--;}break;
  case 0: while (n) {*q3.w++ =(short)(*q2.b++)-(x.w);n--;}break;
  case 4: x.d=(double)x.w; while (n) {*q3.d++ =(*q2.d++)-(x.d);n--;}break;
 }	break;
 case 0:	 x.b = *p1.b;
  switch (type2)	{
  case 0: while (n) {*q3.b++ =(*q2.b++)-(x.b);n--;}break;
  case 1: x.w=(short)x.b; while (n) {*q3.w++ =(*q2.w++)-(x.w);n--;}break;
  case 3: x.f=(float)x.b; while (n) {*q3.f++ =(*q2.f++)-(x.f);n--;}break;
  case 2: x.l=(int)x.b; while (n) {*q3.l++ =(*q2.l++)-(x.l);n--;}break;
  case 4: x.d=(double)x.b; while (n) {*q3.d++ =(*q2.d++)-(x.d);n--;}break;
 }	break;
 case 4:  x.d = *p1.d;	
  switch (type2)	{
  case 4: while (n) {*q3.d++ =(*q2.d++)-(x.d);n--;}break;
  case 3: while (n) {*q3.d++ =(double)(*q2.f++)-(x.d);n--;}break;
  case 0: while (n) {*q3.d++ =(double)(*q2.b++)-(x.d);n--;}break;
  case 1: while (n) {*q3.d++ =(double)(*q2.w++)-(x.d);n--;}break;
  case 2: while (n) {*q3.d++ =(double)(*q2.l++)-(x.d);n--;}break;
 }	break;
 }
 return result_sym;
 }
 /*------------------------------------------------------------------------- */
int	ana_mul()
 /*muliply 2 symbols */
 {
 register union	types_ptr q1,q2,q3;
 register int n;
 q1.l = p1.l;	q2.l = p2.l;	q3.l = p3.l;	n = nelem;
 switch (type1)	{
 case 3:	switch (type2)	{
  case 3: while (n) {*q3.f++ =(*q1.f++)*(*q2.f++);n--; }break;
  case 2: while (n) {*q3.f++ =(*q1.f++)*(float)(*q2.l++);n--;}break;
  case 1: while (n) {*q3.f++ =(*q1.f++)*(float)(*q2.w++);n--;}break;
  case 0: while (n) {*q3.f++ =(*q1.f++)*(float)(*q2.b++);n--;}break;
  case 4: while (n) {*q3.d++ =(double)(*q1.f++)*(*q2.d++);n--;}break;
 }	break;
 case 2:	switch (type2)	{
  case 2: while (n) {*q3.l++ =(*q1.l++)*(*q2.l++);n--;}break;
  case 3: while (n) {*q3.f++ =(float)(*q1.l++)*(*q2.f++);n--;}break;
  case 1: while (n) {*q3.l++ =(*q1.l++)*(int)(*q2.w++);n--;}break;
  case 0: while (n) {*q3.l++ =(*q1.l++)*(int)(*q2.b++);n--;}break;
  case 4: while (n) {*q3.d++ =(double)(*q1.l++)*(*q2.d++);n--;}break;
 }	break;
 case 1:	switch (type2)	{
  case 1: while (n) {*q3.w++ =(*q1.w++)*(*q2.w++);n--;}break;
  case 3: while (n) {*q3.f++ =(float)(*q1.w++)*(*q2.f++);n--;}break;
  case 2: while (n) {*q3.l++ =(int)(*q1.w++)*(*q2.l++);n--;}break;
  case 0: while (n) {*q3.w++ =(*q1.w++)*(short)(*q2.b++);n--;}break;
  case 4: while (n) {*q3.d++ =(double)(*q1.w++)*(*q2.d++);n--;}break;
 }	break;
 case 0:	switch (type2)	{
  case 0: while (n) {*q3.b++ =(*q1.b++)*(*q2.b++);n--;}break;
  case 1: while (n) {*q3.w++ =(short)(*q1.b++)*(*q2.w++);n--;}break;
  case 3: while (n) {*q3.f++ =(float)(*q1.b++)*(*q2.f++);n--;}break;
  case 2: while (n) {*q3.l++ =(int)(*q1.b++)*(*q2.l++);n--;}break;
  case 4: while (n) {*q3.d++ =(double)(*q1.b++)*(*q2.d++);n--;}break;
 }	break;
 case 4:	switch (type2)	{
  case 4: while (n) {*q3.d++ =(*q1.d++)*(*q2.d++);n--;}break;
  case 3: while (n) {*q3.d++ =(*q1.d++)*(double)(*q2.f++);n--;}break;
  case 0: while (n) {*q3.d++ =(*q1.d++)*(double)(*q2.b++);n--;}break;
  case 1: while (n) {*q3.d++ =(*q1.d++)*(double)(*q2.w++);n--;}break;
  case 2: while (n) {*q3.d++ =(*q1.d++)*(double)(*q2.l++);n--;}break;
 }	break;
 }
 return result_sym;
 }
 /*------------------------------------------------------------------------- */
int	ana_mul_s_a()
 /*multiply 2 symbols, first a scalar, second an array */
 {
 register union	types_ptr q2,q3;
 register union	scalar x;
 register int n;
 q2.l = p2.l;	q3.l = p3.l;	n = nelem;
 switch (type1)	{
 case 3:  x.f = *p1.f;
  switch (type2)	{
  case 3: while (n) {*q3.f++ =(x.f)*(*q2.f++);n--; }break;
  case 2: while (n) {*q3.f++ =(x.f)*(float)(*q2.l++);n--;}break;
  case 1: while (n) {*q3.f++ =(x.f)*(float)(*q2.w++);n--;}break;
  case 0: while (n) {*q3.f++ =(x.f)*(float)(*q2.b++);n--;}break;
  case 4: x.d = (double) x.f; 
	 while (n) {*q3.d++ =(x.d)*(*q2.d++);n--;}break;
 }	break;
 case 2:	 x.l = *p1.l;
  switch (type2)	{
  case 2: while (n) {*q3.l++ =(x.l)*(*q2.l++);n--;}break;
  case 3: x.f=(float)(x.l); while (n) {*q3.f++ =(x.f)*(*q2.f++);n--;}break;
  case 1: while (n) {*q3.l++ =(x.l)*(int)(*q2.w++);n--;}break;
  case 0: while (n) {*q3.l++ =(x.l)*(int)(*q2.b++);n--;}break;
  case 4: x.d=(double)(x.l); while (n) {*q3.d++ =(x.d)*(*q2.d++);n--;}break;
 }	break;
 case 1:	 x.w = *p1.w;
  switch (type2)	{
  case 1: while (n) {*q3.w++ =(x.w)*(*q2.w++);n--;}break;
  case 3: x.f=(float)x.w; while (n) {*q3.f++ =(x.f)*(*q2.f++);n--;}break;
  case 2: x.l=(int)x.w; while (n) {*q3.l++ =(x.l)*(*q2.l++);n--;}break;
  case 0: while (n) {*q3.w++ =(x.w)*(short)(*q2.b++);n--;}break;
  case 4: x.d=(double)x.w; while (n) {*q3.d++ =(x.d)*(*q2.d++);n--;}break;
 }	break;
 case 0:	 x.b = *p1.b;
  switch (type2)	{
  case 0: while (n) {*q3.b++ =(x.b)*(*q2.b++);n--;}break;
  case 1: x.w=(short)x.b; while (n) {*q3.w++ =(x.w)*(*q2.w++);n--;}break;
  case 3: x.f=(float)x.b; while (n) {*q3.f++ =(x.f)*(*q2.f++);n--;}break;
  case 2: x.l=(int)x.b; while (n) {*q3.l++ =(x.l)*(*q2.l++);n--;}break;
  case 4: x.d=(double)x.b; while (n) {*q3.d++ =(x.d)*(*q2.d++);n--;}break;
 }	break;
 case 4:  x.d = *p1.d;	
  switch (type2)	{
  case 4: while (n) {*q3.d++ =(x.d)*(*q2.d++);n--;}break;
  case 3: while (n) {*q3.d++ =(x.d)*(double)(*q2.f++);n--;}break;
  case 0: while (n) {*q3.d++ =(x.d)*(double)(*q2.b++);n--;}break;
  case 1: while (n) {*q3.d++ =(x.d)*(double)(*q2.w++);n--;}break;
  case 2: while (n) {*q3.d++ =(x.d)*(double)(*q2.l++);n--;}break;
 }	break;
 }
 return result_sym;
 }
 /*------------------------------------------------------------------------- */
int	ana_div()
 /*divide 2 symbols */
 {
 register union	types_ptr q1,q2,q3;
 register int n;
 q1.l = p1.l;	q2.l = p2.l;	q3.l = p3.l;	n = nelem;
 switch (type1)	{
 case 3:	switch (type2)	{
  case 3: while (n) {*q3.f++ =(*q1.f++)/(*q2.f++);n--; }break;
  case 2: while (n) {*q3.f++ =(*q1.f++)/(float)(*q2.l++);n--;}break;
  case 1: while (n) {*q3.f++ =(*q1.f++)/(float)(*q2.w++);n--;}break;
  case 0: while (n) {*q3.f++ =(*q1.f++)/(float)(*q2.b++);n--;}break;
  case 4: while (n) {*q3.d++ =(double)(*q1.f++)/(*q2.d++);n--;}break;
 }	break;
 case 2:	switch (type2)	{
  case 2: while (n) {*q3.l++ =(*q1.l++)/(*q2.l++);n--;}break;
  case 3: while (n) {*q3.f++ =(float)(*q1.l++)/(*q2.f++);n--;}break;
  case 1: while (n) {*q3.l++ =(*q1.l++)/(int)(*q2.w++);n--;}break;
  case 0: while (n) {*q3.l++ =(*q1.l++)/(int)(*q2.b++);n--;}break;
  case 4: while (n) {*q3.d++ =(double)(*q1.l++)/(*q2.d++);n--;}break;
 }	break;
 case 1:	switch (type2)	{
  case 1: while (n) {*q3.w++ =(*q1.w++)/(*q2.w++);n--;}break;
  case 3: while (n) {*q3.f++ =(float)(*q1.w++)/(*q2.f++);n--;}break;
  case 2: while (n) {*q3.l++ =(int)(*q1.w++)/(*q2.l++);n--;}break;
  case 0: while (n) {*q3.w++ =(*q1.w++)/(short)(*q2.b++);n--;}break;
  case 4: while (n) {*q3.d++ =(double)(*q1.w++)/(*q2.d++);n--;}break;
 }	break;
 case 0:	switch (type2)	{
  case 0: while (n) {*q3.b++ =(*q1.b++)/(*q2.b++);n--;}break;
  case 1: while (n) {*q3.w++ =(short)(*q1.b++)/(*q2.w++);n--;}break;
  case 3: while (n) {*q3.f++ =(float)(*q1.b++)/(*q2.f++);n--;}break;
  case 2: while (n) {*q3.l++ =(int)(*q1.b++)/(*q2.l++);n--;}break;
  case 4: while (n) {*q3.d++ =(double)(*q1.b++)/(*q2.d++);n--;}break;
 }	break;
 case 4:	switch (type2)	{
  case 4: while (n) {*q3.d++ =(*q1.d++)/(*q2.d++);n--;}break;
  case 3: while (n) {*q3.d++ =(*q1.d++)/(double)(*q2.f++);n--;}break;
  case 0: while (n) {*q3.d++ =(*q1.d++)/(double)(*q2.b++);n--;}break;
  case 1: while (n) {*q3.d++ =(*q1.d++)/(double)(*q2.w++);n--;}break;
  case 2: while (n) {*q3.d++ =(*q1.d++)/(double)(*q2.l++);n--;}break;
 }	break;
 }
 return result_sym;
 }
 /*------------------------------------------------------------------------- */
int	ana_div_s_a()
 /*divide 2 symbols, first a scalar, second an array */
 {
 register union	types_ptr q2,q3;
 register union	scalar x;
 register int n;
 q2.l = p2.l;	q3.l = p3.l;	n = nelem;
 switch (type1)	{
 case 3:  x.f = *p1.f;
  switch (type2)	{
  case 3: while (n) {*q3.f++ =(x.f)/(*q2.f++);n--; }break;
  case 2: while (n) {*q3.f++ =(x.f)/(float)(*q2.l++);n--;}break;
  case 1: while (n) {*q3.f++ =(x.f)/(float)(*q2.w++);n--;}break;
  case 0: while (n) {*q3.f++ =(x.f)/(float)(*q2.b++);n--;}break;
  case 4: x.d = (double) x.f; 
	 while (n) {*q3.d++ =(x.d)/(*q2.d++);n--;}break;
 }	break;
 case 2:	 x.l = *p1.l;
  switch (type2)	{
  case 2: while (n) {*q3.l++ =(x.l)/(*q2.l++);n--;}break;
  case 3: x.f=(float)(x.l); while (n) {*q3.f++ =(x.f)/(*q2.f++);n--;}break;
  case 1: while (n) {*q3.l++ =(x.l)/(int)(*q2.w++);n--;}break;
  case 0: while (n) {*q3.l++ =(x.l)/(int)(*q2.b++);n--;}break;
  case 4: x.d=(double)(x.l); while (n) {*q3.d++ =(x.d)/(*q2.d++);n--;}break;
 }	break;
 case 1:	 x.w = *p1.w;
  switch (type2)	{
  case 1: while (n) {*q3.w++ =(x.w)/(*q2.w++);n--;}break;
  case 3: x.f=(float)x.w; while (n) {*q3.f++ =(x.f)/(*q2.f++);n--;}break;
  case 2: x.l=(int)x.w; while (n) {*q3.l++ =(x.l)/(*q2.l++);n--;}break;
  case 0: while (n) {*q3.w++ =(x.w)/(short)(*q2.b++);n--;}break;
  case 4: x.d=(double)x.w; while (n) {*q3.d++ =(x.d)/(*q2.d++);n--;}break;
 }	break;
 case 0:	 x.b = *p1.b;
  switch (type2)	{
  case 0: while (n) {*q3.b++ =(x.b)/(*q2.b++);n--;}break;
  case 1: x.w=(short)x.b; while (n) {*q3.w++ =(x.w)/(*q2.w++);n--;}break;
  case 3: x.f=(float)x.b; while (n) {*q3.f++ =(x.f)/(*q2.f++);n--;}break;
  case 2: x.l=(int)x.b; while (n) {*q3.l++ =(x.l)/(*q2.l++);n--;}break;
  case 4: x.d=(double)x.b; while (n) {*q3.d++ =(x.d)/(*q2.d++);n--;}break;
 }	break;
 case 4:  x.d = *p1.d;	
  switch (type2)	{
  case 4: while (n) {*q3.d++ =(x.d)/(*q2.d++);n--;}break;
  case 3: while (n) {*q3.d++ =(x.d)/(double)(*q2.f++);n--;}break;
  case 0: while (n) {*q3.d++ =(x.d)/(double)(*q2.b++);n--;}break;
  case 1: while (n) {*q3.d++ =(x.d)/(double)(*q2.w++);n--;}break;
  case 2: while (n) {*q3.d++ =(x.d)/(double)(*q2.l++);n--;}break;
 }	break;
 }
 return result_sym;
 }
 /*------------------------------------------------------------------------- */
int	ana_div_a_s()
 /*div 2 symbols, for original array/scalar case, symbol #'s were reversed */
 {
 register union	types_ptr q2,q3;
 register union	scalar x;
 register int n;
 q2.l = p2.l;	q3.l = p3.l;	n = nelem;
 switch (type1)	{
 case 3:  x.f = *p1.f;
  switch (type2)	{
  case 3: while (n) {*q3.f++ =(*q2.f++)/(x.f);n--; }break;
  case 2: while (n) {*q3.f++ =(float)(*q2.l++)/(x.f);n--;}break;
  case 1: while (n) {*q3.f++ =(float)(*q2.w++)/(x.f);n--;}break;
  case 0: while (n) {*q3.f++ =(float)(*q2.b++)/(x.f);n--;}break;
  case 4: x.d = (double) x.f; 
	 while (n) {*q3.d++ =(*q2.d++)/(x.d);n--;}break;
 }	break;
 case 2:	 x.l = *p1.l;
  switch (type2)	{
  case 2: while (n) {*q3.l++ =(*q2.l++)/(x.l);n--;}break;
  case 3: x.f=(float)(x.l); while (n) {*q3.f++ =(*q2.f++)/(x.f);n--;}break;
  case 1: while (n) {*q3.l++ =(int)(*q2.w++)/(x.l);n--;}break;
  case 0: while (n) {*q3.l++ =(int)(*q2.b++)/(x.l);n--;}break;
  case 4: x.d=(double)(x.l); while (n) {*q3.d++ =(*q2.d++)/(x.d);n--;}break;
 }	break;
 case 1:	 x.w = *p1.w;
  switch (type2)	{
  case 1: while (n) {*q3.w++ =(*q2.w++)/(x.w);n--;}break;
  case 3: x.f=(float)x.w; while (n) {*q3.f++ =(*q2.f++)/(x.f);n--;}break;
  case 2: x.l=(int)x.w; while (n) {*q3.l++ =(*q2.l++)/(x.l);n--;}break;
  case 0: while (n) {*q3.w++ =(short)(*q2.b++)/(x.w);n--;}break;
  case 4: x.d=(double)x.w; while (n) {*q3.d++ =(*q2.d++)/(x.d);n--;}break;
 }	break;
 case 0:	 x.b = *p1.b;
  switch (type2)	{
  case 0: while (n) {*q3.b++ =(*q2.b++)/(x.b);n--;}break;
  case 1: x.w=(short)x.b; while (n) {*q3.w++ =(*q2.w++)/(x.w);n--;}break;
  case 3: x.f=(float)x.b; while (n) {*q3.f++ =(*q2.f++)/(x.f);n--;}break;
  case 2: x.l=(int)x.b; while (n) {*q3.l++ =(*q2.l++)/(x.l);n--;}break;
  case 4: x.d=(double)x.b; while (n) {*q3.d++ =(*q2.d++)/(x.d);n--;}break;
 }	break;
 case 4:  x.d = *p1.d;	
  switch (type2)	{
  case 4: while (n) {*q3.d++ =(*q2.d++)/(x.d);n--;}break;
  case 3: while (n) {*q3.d++ =(double)(*q2.f++)/(x.d);n--;}break;
  case 0: while (n) {*q3.d++ =(double)(*q2.b++)/(x.d);n--;}break;
  case 1: while (n) {*q3.d++ =(double)(*q2.w++)/(x.d);n--;}break;
  case 2: while (n) {*q3.d++ =(double)(*q2.l++)/(x.d);n--;}break;
 }	break;
 }
 return result_sym;
 }
 /*------------------------------------------------------------------------- */
int	ana_mod()
 /*modulus 2 symbols */
 {
 register union	types_ptr q1,q2,q3;
 register int n;
 double	xq, yq, zq;
 int	iq;
 q1.l = p1.l;	q2.l = p2.l;	q3.l = p3.l;	n = nelem;
 switch (type1)	{
 case 3:	switch (type2)	{
  case 3: while (n)
#if defined(SOLARIS)
   {*q3.f++ = copysign(fmod(fabs(*q1.f),fabs(*q2.f)),*q1.f);
#else
   {*q3.f++ = copysign(fmodf(fabsf(*q1.f),fabsf(*q2.f)),*q1.f);
#endif
   q1.f++; q2.f++; n--;} break;
  case 2: while (n)
#if defined(SOLARIS)
   {*q3.f++ = copysign(fmod(fabs(*q1.f),fabs( (float) *q2.l)),*q1.f);
#else
   {*q3.f++ = copysign(fmodf(fabsf(*q1.f),fabsf( (float) *q2.l)),*q1.f);
#endif
   q1.f++; q2.l++; n--;} break;
  case 1: while (n)
#if defined(SOLARIS)
   {*q3.f++ = copysign(fmod(fabs(*q1.f),fabs( (float) *q2.w)),*q1.f);
#else
   {*q3.f++ = copysign(fmodf(fabsf(*q1.f),fabsf( (float) *q2.w)),*q1.f);
#endif
   q1.f++; q2.w++; n--;} break;
  case 0: while (n)
#if defined(SOLARIS)
   {*q3.f++ = copysign(fmod(fabs(*q1.f),fabs( (float) *q2.b)),*q1.f);
#else
   {*q3.f++ = copysign(fmodf(fabsf(*q1.f),fabsf( (float) *q2.b)),*q1.f);
#endif
   q1.f++; q2.b++; n--;} break;
  case 4: while (n)
   {*q3.d++ = copysign(fmod(fabs( (double) *q1.f),fabs(*q2.d)),*q1.f);
   q1.f++; q2.d++; n--;} break;
 }	break;
 case 2:	switch (type2)	{
  case 2: while (n) {*q3.l++ = (*q1.l++) % (*q2.l++); n--; } break;
  case 3: while (n)
#if defined(SOLARIS)
   {*q3.f++ = copysign(fmod(fabs( (float) *q1.l),fabs(*q2.f)),*q1.l);
#else
   {*q3.f++ = copysign(fmodf(fabsf( (float) *q1.l),fabsf(*q2.f)),*q1.l);
#endif
   q1.l++; q2.f++; n--; } break;
  case 1: while (n) {*q3.l++ = (*q1.l++) % (int) (*q2.w++); n--;} break;
  case 0: while (n) {*q3.l++ = (*q1.l++) % (int) (*q2.b++); n--;} break;
  case 4: while (n)
   {*q3.d++ = copysign(fmod(fabs( (double) *q1.l),fabs(*q2.d)),*q1.l);
   q1.l++; q2.d++; n--; } break;
 }	break;
 case 1:	switch (type2)	{
  case 1: while (n) {*q3.w++ = (*q1.w++) % (*q2.w++); n--; } break;
  case 3: while (n)
#if defined(SOLARIS)
   {*q3.f++ = copysign(fmod(fabs( (float) *q1.w),fabs(*q2.f)),*q1.w);  
#else
   {*q3.f++ = copysign(fmodf(fabsf( (float) *q1.w),fabs(*q2.f)),*q1.w);  
#endif
   q1.w++; q2.f++; n--; } break;
  case 2: while (n) {*q3.l++ = (int) (*q1.w++) % (*q2.l++); n--;} break;
  case 0: while (n) {*q3.w++ = (*q1.w++) % (short) (*q2.b++); n--;} break;
  case 4: while (n)
   {*q3.d++ = copysign(fmod(fabs( (double) *q1.w),fabs(*q2.d)),*q1.w);
   q1.w++; q2.d++; n--; } break;
 }	break;
 case 0:	switch (type2)	{
  case 0: while (n) {*q3.b++ = (*q1.b++) %(*q2.b++); n--;} break;
  case 1: while (n) {*q3.w++ = (short) (*q1.b++) % (*q2.w++); n--;} break;
  case 3: while (n)
#if defined(SOLARIS)
   {*q3.f++ = copysign(fmod(fabs( (float) *q1.b),fabs(*q2.f)),*q1.b);
#else
   {*q3.f++ = copysign(fmodf(fabsf( (float) *q1.b),fabsf(*q2.f)),*q1.b);
#endif
   q1.b++; q2.f++; n--; } break;
  case 2: while (n) {*q3.l++ = (int) (*q1.b++) % (*q2.l++); n--;} break;
  case 4: while (n)
   {*q3.d++ = copysign(fmod(fabs( (double) *q1.b),fabs(*q2.d)),*q1.b);
   q1.b++; q2.d++; n--; } break;
 }	break;
 case 4:	switch (type2)	{
  case 4: while (n)
   {*q3.d++ = copysign(fmod(fabs( *q1.d),fabs(*q2.d)),*q1.d);
   q1.d++; q2.d++; n--; } break;
  case 3: while (n)
   {*q3.d++ = copysign(fmod(fabs(*q1.d),fabs( (double) *q2.f)),*q1.d);
   q1.d++; q2.f++; n--; } break;
  case 2: while (n)
   {*q3.d++ = copysign(fmod(fabs(*q1.d),fabs( (double) *q2.l)),*q1.d);
   q1.d++; q2.l++; n--; } break;
  case 1: while (n)
   {*q3.d++ = copysign(fmod(fabs(*q1.d),fabs( (double) *q2.w)),*q1.d);
   q1.d++; q2.w++; n--; } break;
  case 0: while (n)
   {*q3.d++ = copysign(fmod(fabs(*q1.d),fabs( (double) *q2.b)),*q1.d);
   q1.d++; q2.b++; n--; } break;
 }	break;
 }
 return result_sym;
 }
 /*------------------------------------------------------------------------- */
int	ana_mod_s_a()
 /*modulus 2 symbols */
 {
 register union	types_ptr q2,q3;
 register union	scalar x;
 register int n;
 q2.l = p2.l;	q3.l = p3.l;	n = nelem;
 switch (type1)	{
 case 3:  x.f = *p1.f;
 switch (type2)	{
  case 3: while (n)
#if defined(SOLARIS)
   {*q3.f++ = copysign(fmod(fabs(x.f),fabs(*q2.f)),x.f);
#else
   {*q3.f++ = copysign(fmodf(fabsf(x.f),fabsf(*q2.f)),x.f);
#endif
   q2.f++; n--;} break;
  case 2: while (n)
#if defined(SOLARIS)
   {*q3.f++ = copysign(fmod(fabs(x.f),fabs( (float) *q2.l)),x.f);
#else
   {*q3.f++ = copysign(fmodf(fabsf(x.f),fabsf( (float) *q2.l)),x.f);
#endif
   q2.l++; n--;} break;
  case 1: while (n)
#if defined(SOLARIS)
   {*q3.f++ = copysign(fmod(fabs(x.f),fabs( (float) *q2.w)),x.f);
#else
   {*q3.f++ = copysign(fmodf(fabsf(x.f),fabsf( (float) *q2.w)),x.f);
#endif
   q2.w++; n--;} break;
  case 0: while (n)
#if defined(SOLARIS)
   {*q3.f++ = copysign(fmod(fabs(x.f),fabs( (float) *q2.b)),x.f);
#else
   {*q3.f++ = copysign(fmodf(fabsf(x.f),fabsf( (float) *q2.b)),x.f);
#endif
   q2.b++; n--;} break;
  case 4: while (n)
   {*q3.d++ = copysign(fmod(fabs( (double) x.f),fabs(*q2.d)),x.f);
   q2.d++; n--;} break;
 }	break;
 case 2:
  switch (type2)	{
  case 0: x.l = *p1.l;
  while (n) {*q3.l++ = (x.l) % (int) (*q2.b++); n--;} break;
  case 1: x.l = *p1.l;
  while (n) {*q3.l++ = (x.l) % (int) (*q2.w++); n--;} break;
  case 2: x.l = *p1.l;
  while (n) {*q3.l++ = (x.l) % (*q2.l++);       n--;} break;
  case 3: x.f = (float) *p1.l;
#if defined(SOLARIS)
  while (n) {*q3.f++ = copysign(fmod(fabs(x.f),fabs(*q2.f)),x.f);
#else
  while (n) {*q3.f++ = copysign(fmodf(fabsf(x.f),fabsf(*q2.f)),x.f);
#endif
  q2.f++; n--; } break;
  case 4: x.d = (double) *p1.l;
  while (n) {*q3.d++ = copysign(fmod(fabs(x.d),fabs(*q2.d)),x.d);
  q2.d++; n--; } break;
 }	break;
 case 1:
  switch (type2)	{
  case 1:  x.w = *p1.w;
  while (n) {*q3.w++ = (x.w) % (*q2.w++); n--; } break;
  case 2:   x.l = (int) *p1.w;
  while (n) {*q3.l++ = x.l % (*q2.l++); n--;} break;
  case 0:  x.w = *p1.w;
  while (n) {*q3.w++ = (x.w) % (short) (*q2.b++); n--;} break;
  case 3: x.f = (float) *p1.w;
#if defined(SOLARIS)
  while (n) {*q3.f++ = copysign(fmod(fabs(x.f),fabs(*q2.f)), x.f);
#else
  while (n) {*q3.f++ = copysign(fmodf(fabsf(x.f),fabsf(*q2.f)), x.f);
#endif
  q2.f++; n--; } break;
  case 4: x.d = (double) *p1.w;
  while (n) {*q3.d++ = copysign(fmod(fabs(x.d),fabs(*q2.d)),x.d);
  q2.d++; n--; } break;
 }	break;
 case 0:  x.b = *p1.b;
  switch (type2)	{
  case 0:  x.b = *p1.b;
  while (n) {*q3.b++ = (x.b) %(*q2.b++); n--;} break;
  case 1:  x.w = (short) *p1.b;
  while (n) {*q3.w++ = x.w % (*q2.w++); n--;} break;
  case 2:  x.l = (int) *p1.b;
  while (n) {*q3.l = x.l % (*q2.l++); n--;} break;
  case 3: x.f = (float) *p1.b;
#if defined(SOLARIS)
  while (n) {*q3.f++ = copysign(fmod(fabs(x.f),fabs(*q2.f)), x.f);
#else
  while (n) {*q3.f++ = copysign(fmodf(fabsf(x.f),fabsf(*q2.f)), x.f);
#endif
  q2.f++; n--; } break;
  case 4: x.d = (double) *p1.b;
  while (n) {*q3.d++ = copysign(fmod(fabs(x.d),fabs(*q2.d)),x.d);
  q2.d++; n--; } break;
 }	break;
 case 4:  x.d = *p1.d;
  switch (type2)	{
  case 4: while (n)
   {*q3.d++ = copysign(fmod(fabs(x.d),fabs(*q2.d)),x.d);
   q2.d++; n--; } break;
  case 3: while (n)
   {*q3.d++ = copysign(fmod(fabs(x.d),fabs( (double) *q2.f)),x.d);
   q2.f++; n--; } break;
  case 2: while (n)
   {*q3.d++ = copysign(fmod(fabs(x.d),fabs( (double) *q2.l)),x.d);
   q2.l++; n--; } break;
  case 1: while (n)
   {*q3.d++ = copysign(fmod(fabs(x.d),fabs( (double) *q2.w)),x.d);
   q2.w++; n--; } break;
  case 0: while (n)
   {*q3.d++ = copysign(fmod(fabs(x.d),fabs( (double) *q2.b)),x.d);
   q2.b++; n--; } break;
 }	break;
 }
 return result_sym;
 }
 /*------------------------------------------------------------------------- */
int	ana_mod_a_s()
 /*modulus 2 symbols */
 {
 register union	types_ptr q2,q3;
 register union	scalar x;
 register int n;
 q2.l = p2.l;	q3.l = p3.l;	n = nelem;
 switch (type1)	{
 case 3:  x.f =  *p1.f;
 switch (type2)	{
  case 3: while (n)
#if defined(SOLARIS)
   {*q3.f++ = copysign(fmod(fabs(*q2.f),fabs(x.f)),*q2.f);
#else
   {*q3.f++ = copysign(fmodf(fabsf(*q2.f),fabsf(x.f)),*q2.f);
#endif
   q2.f++; n--;} break;
  case 2: while (n)
#if defined(SOLARIS)
   {*q3.f++ = copysign(fmod(fabs( (float) *q2.l),fabs(x.f)),*q2.l);
#else
   {*q3.f++ = copysign(fmodf(fabsf( (float) *q2.l),fabsf(x.f)),*q2.l);
#endif
   q2.l++; n--;} break;
  case 1: while (n)
#if defined(SOLARIS)
   {*q3.f++ = copysign(fmod(fabs( (float) *q2.w),fabs(x.f)),*q2.w);
#else
   {*q3.f++ = copysign(fmodf(fabsf( (float) *q2.w),fabsf(x.f)),*q2.w);
#endif
   q2.w++; n--;} break;
  case 0: while (n)
#if defined(SOLARIS)
   {*q3.f++ = copysign(fmod(fabs( (float) *q2.b),fabs(x.f)),*q2.b);
#else
   {*q3.f++ = copysign(fmodf(fabsf( (float) *q2.b),fabsf(x.f)),*q2.b);
#endif
   q2.b++; n--;} break;
  case 4: 
   x.d = (double) *p1.f;
   while (n) {*q3.d++ = copysign(fmod(fabs(*q2.d),fabs(x.d)),*q2.d);
   q2.d++; n--;} break;
 }	break;
 case 2:
  switch (type2)	{
  case 0: x.l = *p1.l;
  while (n) {*q3.l++ = (*q2.b++) % (int) (x.l); n--;} break;
  case 1: x.l = *p1.l;
  while (n) {*q3.l++ = (*q2.w++) % (int) (x.l); n--;} break;
  case 2: x.l = *p1.l;
  while (n) {*q3.l++ = (*q2.l++) % (x.l);       n--;} break;
  case 3: x.f = (float) *p1.l;
#if defined(SOLARIS)
  while (n) {*q3.f++ = copysign(fmod(fabs(*q2.f),fabs(x.f)),*q2.f);
#else
  while (n) {*q3.f++ = copysign(fmodf(fabsf(*q2.f),fabsf(x.f)),*q2.f);
#endif
  q2.f++; n--; } break;
  case 4: x.d = (double) *p1.l;
  while (n) {*q3.d++ = copysign(fmod(fabs(*q2.d),fabs(x.d)),*q2.d);
  q2.d++; n--; } break;
 }	break;
 case 1:
  switch (type2)	{
  case 1:  x.w = *p1.w;
  while (n) {*q3.w++ = (*q2.w++) % (x.w); n--; } break;
  case 2:   x.l = (int) *p1.w;
  while (n) {*q3.l++ = *q2.l++ % (x.l); n--;} break;
  case 0:  x.w = *p1.w;
  while (n) {*q3.w++ = (short) (*q2.b++) % x.w ; n--;} break;
  case 3: x.f = (float) *p1.w;
#if defined(SOLARIS)
  while (n) {*q3.f++ = copysign(fmod(fabs(*q2.f),fabs(x.f)),*q2.f);
#else
  while (n) {*q3.f++ = copysign(fmodf(fabsf(*q2.f),fabsf(x.f)),*q2.f);
#endif
  q2.f++; n--; } break;
  case 4: x.d = (double) *p1.w;
  while (n) {*q3.d++ = copysign(fmod(fabs(*q2.d),fabs(x.d)),*q2.d);
  q2.d++; n--; } break;
 }	break;
 case 0:
  switch (type2)	{
  case 0:  x.b = *p1.b;
  while (n) {*q3.b++ = (*q2.b++) % x.b; n--;} break;
  case 1:  x.w = (short) *p1.b;
  while (n) {*q3.w++ = (*q2.w++) % x.w; n--;} break;
  case 2:  x.l = (int) *p1.b;
  while (n) {*q3.l = (*q2.l++) % x.l; n--;} break;
  case 3: x.f = (float) *p1.b;
#if defined(SOLARIS)
  while (n) {*q3.f++ = copysign(fmod(fabs(*q2.f),fabs(x.f)),*q2.f);
#else
  while (n) {*q3.f++ = copysign(fmodf(fabsf(*q2.f),fabsf(x.f)),*q2.f);
#endif
  q2.f++; n--; } break;
  case 4: x.d = (double) *p1.b;
  while (n) {*q3.d++ = copysign(fmod(fabs(*q2.d),fabs(x.d)),*q2.d);
  q2.d++; n--; } break;
 }	break;
 case 4:  x.d = *p1.d;
  switch (type2)	{
  case 4: while (n)
   {*q3.d++ = copysign(fmod(fabs(*q2.d),fabs(x.d)),*q2.d);
   q2.d++; n--; } break;
  case 3: while (n)
   {*q3.d++ = copysign(fmod(fabs( (double) *q2.f),fabs(x.d)),*q2.f);
   q2.f++; n--; } break;
  case 2: while (n)
   {*q3.d++ = copysign(fmod(fabs( (double) *q2.l),fabs(x.d)),*q2.l);
   q2.l++; n--; } break;
  case 1: while (n)
   {*q3.d++ = copysign(fmod(fabs( (double) *q2.w),fabs(x.d)),*q2.w);
   q2.w++; n--; } break;
  case 0: while (n)
   {*q3.d++ = copysign(fmod(fabs( (double) *q2.b),fabs(x.d)),*q2.b);
   q2.b++; n--; } break;
 }	break;
 }
 return result_sym;
 }
 /*------------------------------------------------------------------------- */
int	ana_max()
 /*get max of 2 symbols */
 {
 register union	types_ptr q1,q2,q3;
 register int n;
 q1.l = p1.l;	q2.l = p2.l;	q3.l = p3.l;	n = nelem;
 switch (type1)	{
 case 3:	switch (type2)	{
  case 3: while (n) {
	 if ( *q1.f >= *q2.f ) *q3.f++ = *q1.f; else *q3.f++ = *q2.f;
	 q1.f++; q2.f++; n--; }break;
  case 2: while (n) {
	 if ( *q1.f >= *q2.l ) *q3.f++ = *q1.f; else *q3.f++ = *q2.l;
	 q1.f++; q2.l++; n--;}break;
  case 1: while (n) {
	 if ( *q1.f >= *q2.w ) *q3.f++ = *q1.f; else *q3.f++ = *q2.w;
	 q1.f++; q2.w++; n--;}break;
  case 0: while (n) {
	 if ( *q1.f >= *q2.b ) *q3.f++ = *q1.f; else *q3.f++ = *q2.b;
	 q1.f++; q2.b++; n--;}break;
  case 4: while (n) {
	 if ( *q1.f >= *q2.d ) *q3.d++ = *q1.f; else *q3.d++ = *q2.d;
	 q1.f++; q2.d++; n--;}break;
 }	break;
 case 2:	switch (type2)	{
  case 2: while (n) {
	 if ( *q1.l >= *q2.l ) *q3.l++ = *q1.l; else *q3.l++ = *q2.l;
	 q1.l++; q2.l++; n--;}break;
  case 3: while (n) {
	 if ( *q1.l >= *q2.f ) *q3.f++ = *q1.l; else *q3.f++ = *q2.f;
	 q1.l++; q2.f++; n--; }break;
  case 1: while (n) {
	 if ( *q1.l >= *q2.w ) *q3.l++ = *q1.l; else *q3.l++ = *q2.w;
	 q1.l++; q2.w++; n--;}break;
  case 0: while (n) {
	 if ( *q1.l >= *q2.b ) *q3.l++ = *q1.l; else *q3.l++ = *q2.b;
	 q1.l++; q2.b++; n--;}break;
  case 4: while (n) {
	 if ( *q1.l >= *q2.d ) *q3.d++ = *q1.l; else *q3.d++ = *q2.d;
	 q1.l++; q2.d++; n--;}break;
 }	break;
 case 1:	switch (type2)	{
  case 1: while (n) {
	 if ( *q1.w >= *q2.w ) *q3.w++ = *q1.w; else *q3.w++ = *q2.w;
	 q1.w++; q2.w++; n--;}break;
  case 3: while (n) {
	 if ( *q1.w >= *q2.f ) *q3.f++ = *q1.w; else *q3.f++ = *q2.f;
	 q1.w++; q2.f++; n--; }break;
  case 2: while (n) {
	 if ( *q1.w >= *q2.l ) *q3.l++ = *q1.w; else *q3.l++ = *q2.l;
	 q1.w++; q2.l++; n--;}break;
  case 0: while (n) {
	 if ( *q1.w >= *q2.b ) *q3.w++ = *q1.w; else *q3.w++ = *q2.b;
	 q1.w++; q2.b++; n--;}break;
  case 4: while (n) {
	 if ( *q1.w >= *q2.d ) *q3.d++ = *q1.w; else *q3.d++ = *q2.d;
	 q1.w++; q2.d++; n--;}break;
 }	break;
 case 0:	switch (type2)	{
  case 0: while (n) {
	 if ( *q1.b >= *q2.b ) *q3.b++ = *q1.b; else *q3.b++ = *q2.b;
	 q1.b++; q2.b++; n--;}break;
  case 3: while (n) {
	 if ( *q1.b >= *q2.f ) *q3.f++ = *q1.b; else *q3.f++ = *q2.f;
	 q1.b++; q2.f++; n--; }break;
  case 2: while (n) {
	 if ( *q1.b >= *q2.l ) *q3.l++ = *q1.b; else *q3.l++ = *q2.l;
	 q1.b++; q2.l++; n--;}break;
  case 1: while (n) {
	 if ( *q1.b >= *q2.w ) *q3.w++ = *q1.b; else *q3.w++ = *q2.w;
	 q1.b++; q2.w++; n--;}break;
  case 4: while (n) {
	 if ( *q1.b >= *q2.d ) *q3.d++ = *q1.b; else *q3.d++ = *q2.d;
	 q1.b++; q2.d++; n--;}break;
 }	break;
 case 4:	switch (type2)	{
  case 4: while (n) {
	 if ( *q1.d >= *q2.d ) *q3.d++ = *q1.d; else *q3.d++ = *q2.d;
	 q1.d++; q2.d++; n--;}break;
  case 3: while (n) {
	 if ( *q1.d >= *q2.f ) *q3.d++ = *q1.d; else *q3.d++ = *q2.f;
	 q1.d++; q2.f++; n--; }break;
  case 2: while (n) {
	 if ( *q1.d >= *q2.l ) *q3.d++ = *q1.d; else *q3.d++ = *q2.l;
	 q1.d++; q2.l++; n--;}break;
  case 1: while (n) {
	 if ( *q1.d >= *q2.w ) *q3.d++ = *q1.d; else *q3.d++ = *q2.w;
	 q1.d++; q2.w++; n--;}break;
  case 0: while (n) {
	 if ( *q1.d >= *q2.b ) *q3.d++ = *q1.d; else *q3.d++ = *q2.b;
	 q1.d++; q2.b++; n--;}break;
 }	break;
 }
 return result_sym;
 }
 /*------------------------------------------------------------------------- */
int	ana_max_s_a()
 /*get max of 2 symbols */
 {
 register union	types_ptr q2,q3;
 register union	scalar x;
 register int n;
 q2.l = p2.l;	q3.l = p3.l;	n = nelem;
 switch (type1)	{
 case 3: x.f = *p1.f;
  switch (type2)	{
  case 3: while (n) {
	 if ( x.f >= *q2.f ) *q3.f++ = x.f; else *q3.f++ = *q2.f;
	 q2.f++; n--; }break;
  case 2: while (n) {
	 if ( x.f >= *q2.l ) *q3.f++ = x.f; else *q3.f++ = *q2.l;
	 q2.l++; n--;}break;
  case 1: while (n) {
	 if ( x.f >= *q2.w ) *q3.f++ = x.f; else *q3.f++ = *q2.w;
	 q2.w++; n--;}break;
  case 0: while (n) {
	 if ( x.f >= *q2.b ) *q3.f++ = x.f; else *q3.f++ = *q2.b;
	 q2.b++; n--;}break;
  case 4: while (n) {
	 if ( x.f >= *q2.d ) *q3.d++ = x.f; else *q3.d++ = *q2.d;
	 q2.d++; n--;}break;
 }	break;
 case 2:	 x.l = *p1.l;
  switch (type2)	{
  case 2: while (n) { 
	 if ( x.l >= *q2.l ) *q3.l++ = x.l; else *q3.l++ = *q2.l;
	 q2.l++; n--;}break;
  case 3: while (n) {
	 if ( x.l >= *q2.f ) *q3.f++ = x.l; else *q3.f++ = *q2.f;
	 q2.f++; n--; }break;
  case 1: while (n) {
	 if ( x.l >= *q2.w ) *q3.l++ = x.l; else *q3.l++ = *q2.w;
	 q2.w++; n--;}break;
  case 0: while (n) {
	 if ( x.l >= *q2.b ) *q3.l++ = x.l; else *q3.l++ = *q2.b;
	 q2.b++; n--;}break;
  case 4: while (n) {
	 if ( x.l >= *q2.d ) *q3.d++ = x.l; else *q3.d++ = *q2.d;
	 q2.d++; n--;}break;
 }	break;
 case 1: x.w = *p1.w;
  switch (type2)	{
  case 1: while (n) {
	 if ( x.w >= *q2.w ) *q3.w++ = x.w; else *q3.w++ = *q2.w;
	 q2.w++; n--;}break;
  case 3: while (n) {
	 if ( x.w >= *q2.f ) *q3.f++ = x.w; else *q3.f++ = *q2.f;
	 q2.f++; n--; }break;
  case 2: while (n) {
	 if ( x.w >= *q2.l ) *q3.l++ = x.w; else *q3.l++ = *q2.l;
	 q2.l++; n--;}break;
  case 0: while (n) {
	 if ( x.w >= *q2.b ) *q3.w++ = x.w; else *q3.w++ = *q2.b;
	 q2.b++; n--;}break;
  case 4: while (n) {
	 if ( x.w >= *q2.d ) *q3.d++ = x.w; else *q3.d++ = *q2.d;
	 q2.d++; n--;}break;
 }	break;
 case 0: x.b = *p1.b;
  switch (type2)	{
  case 0: while (n) {
	 if ( x.b >= *q2.b ) *q3.b++ = x.b; else *q3.b++ = *q2.b;
	 q2.b++; n--;}break;
  case 3: while (n) {
	 if ( x.b >= *q2.f ) *q3.f++ = x.b; else *q3.f++ = *q2.f;
	 q2.f++; n--; }break;
  case 2: while (n) {
	 if ( x.b >= *q2.l ) *q3.l++ = x.b; else *q3.l++ = *q2.l;
	 q2.l++; n--;}break;
  case 1: while (n) {
	 if ( x.b >= *q2.w ) *q3.w++ = x.b; else *q3.w++ = *q2.w;
	 q2.w++; n--;}break;
  case 4: while (n) {
	 if ( x.b >= *q2.d ) *q3.d++ = x.b; else *q3.d++ = *q2.d;
	 q2.d++; n--;}break;
 }	break;
 case 4: x.d = *p1.d;
  switch (type2)	{
  case 4: while (n) {
	 if ( x.d >= *q2.d ) *q3.d++ = x.d; else *q3.d++ = *q2.d;
	 q2.d++; n--;}break;
  case 3: while (n) {
	 if ( x.d >= *q2.f ) *q3.d++ = x.d; else *q3.d++ = *q2.f;
	 q2.f++; n--; }break;
  case 2: while (n) {
	 if ( x.d >= *q2.l ) *q3.d++ = x.d; else *q3.d++ = *q2.l;
	 q2.l++; n--;}break;
  case 1: while (n) {
	 if ( x.d >= *q2.w ) *q3.d++ = x.d; else *q3.d++ = *q2.w;
	 q2.w++; n--;}break;
  case 0: while (n) {
	 if ( x.d >= *q2.b ) *q3.d++ = x.d; else *q3.d++ = *q2.b;
	 q2.b++; n--;}break;
 }	break;
 }
 return result_sym;
 }
 /*------------------------------------------------------------------------- */
int	ana_min()
 /*get min of 2 symbols */
 {
 register union	types_ptr q1,q2,q3;
 register int n;
 q1.l = p1.l;	q2.l = p2.l;	q3.l = p3.l;	n = nelem;
 switch (type1)	{
 case 3:	switch (type2)	{
  case 3: while (n) { 
	 if ( *q1.f <= *q2.f ) *q3.f++ = *q1.f; else *q3.f++ = *q2.f;
	 q1.f++; q2.f++; n--; }break;
  case 2: while (n) {
	 if ( *q1.f <= *q2.l ) *q3.f++ = *q1.f; else *q3.f++ = *q2.l;
	 q1.f++; q2.l++; n--;}break;
  case 1: while (n) {
	 if ( *q1.f <= *q2.w ) *q3.f++ = *q1.f; else *q3.f++ = *q2.w;
	 q1.f++; q2.w++; n--;}break;
  case 0: while (n) {
	 if ( *q1.f <= *q2.b ) *q3.f++ = *q1.f; else *q3.f++ = *q2.b;
	 q1.f++; q2.b++; n--;}break;
  case 4: while (n) {
	 if ( *q1.f <= *q2.d ) *q3.d++ = *q1.f; else *q3.d++ = *q2.d;
	 q1.f++; q2.d++; n--;}break;
 }	break;
 case 2:	switch (type2)	{
  case 2: while (n) {
	 if ( *q1.l <= *q2.l ) *q3.l++ = *q1.l; else *q3.l++ = *q2.l;
	 q1.l++; q2.l++; n--;}break;
  case 3: while (n) {
	 if ( *q1.l <= *q2.f ) *q3.f++ = *q1.l; else *q3.f++ = *q2.f;
	 q1.l++; q2.f++; n--; }break;
  case 1: while (n) {
	 if ( *q1.l <= *q2.w ) *q3.l++ = *q1.l; else *q3.l++ = *q2.w;
	 q1.l++; q2.w++; n--;}break;
  case 0: while (n) {
	 if ( *q1.l <= *q2.b ) *q3.l++ = *q1.l; else *q3.l++ = *q2.b;
	 q1.l++; q2.b++; n--;}break;
  case 4: while (n) {
	 if ( *q1.l <= *q2.d ) *q3.d++ = *q1.l; else *q3.d++ = *q2.d;
	 q1.l++; q2.d++; n--;}break;
 }	break;
 case 1:	switch (type2)	{
  case 1: while (n) {
	 if ( *q1.w <= *q2.w ) *q3.w++ = *q1.w; else *q3.w++ = *q2.w;
	 q1.w++; q2.w++; n--;}break;
  case 3: while (n) {
	 if ( *q1.w <= *q2.f ) *q3.f++ = *q1.w; else *q3.f++ = *q2.f;
	 q1.w++; q2.f++; n--; }break;
  case 2: while (n) {
	 if ( *q1.w <= *q2.l ) *q3.l++ = *q1.w; else *q3.l++ = *q2.l;
	 q1.w++; q2.l++; n--;}break;
  case 0: while (n) {
	 if ( *q1.w <= *q2.b ) *q3.w++ = *q1.w; else *q3.w++ = *q2.b;
	 q1.w++; q2.b++; n--;}break;
  case 4: while (n) {
	 if ( *q1.w <= *q2.d ) *q3.d++ = *q1.w; else *q3.d++ = *q2.d;
	 q1.w++; q2.d++; n--;}break;
 }	break;
 case 0:	switch (type2)	{
  case 0: while (n) {
	 if ( *q1.b <= *q2.b ) *q3.b++ = *q1.b; else *q3.b++ = *q2.b;
	 q1.b++; q2.b++; n--;}break;
  case 3: while (n) {
	 if ( *q1.b <= *q2.f ) *q3.f++ = *q1.b; else *q3.f++ = *q2.f;
	 q1.b++; q2.f++; n--; }break;
  case 2: while (n) {
	 if ( *q1.b <= *q2.l ) *q3.l++ = *q1.b; else *q3.l++ = *q2.l;
	 q1.b++; q2.l++; n--;}break;
  case 1: while (n) {
	 if ( *q1.b <= *q2.w ) *q3.w++ = *q1.b; else *q3.w++ = *q2.w;
	 q1.b++; q2.w++; n--;}break;
  case 4: while (n) {
	 if ( *q1.b <= *q2.d ) *q3.d++ = *q1.b; else *q3.d++ = *q2.d;
	 q1.b++; q2.d++; n--;}break;
 }	break;
 case 4:	switch (type2)	{
  case 4: while (n) {
	 if ( *q1.d <= *q2.d ) *q3.d++ = *q1.d; else *q3.d++ = *q2.d;
	 q1.d++; q2.d++; n--;}break;
  case 3: while (n) {
	 if ( *q1.d <= *q2.f ) *q3.d++ = *q1.d; else *q3.d++ = *q2.f;
	 q1.d++; q2.f++; n--; }break;
  case 2: while (n) {
	 if ( *q1.d <= *q2.l ) *q3.d++ = *q1.d; else *q3.d++ = *q2.l;
	 q1.d++; q2.l++; n--;}break;
  case 1: while (n) {
	 if ( *q1.d <= *q2.w ) *q3.d++ = *q1.d; else *q3.d++ = *q2.w;
	 q1.d++; q2.w++; n--;}break;
  case 0: while (n) {
	 if ( *q1.d <= *q2.b ) *q3.d++ = *q1.d; else *q3.d++ = *q2.b;
	 q1.d++; q2.b++; n--;}break;
 }	break;
 }
 return result_sym;
 }
 /*------------------------------------------------------------------------- */
int	ana_min_s_a()
 /*get min of 2 symbols */
 {
 register union	types_ptr q2,q3;
 register union	scalar x;
 register int n;
 q2.l = p2.l;	q3.l = p3.l;	n = nelem;
 switch (type1)	{
 case 3: x.f = *p1.f;
  switch (type2)	{
  case 3: while (n) {
	 if ( x.f <= *q2.f ) *q3.f++ = x.f; else *q3.f++ = *q2.f;
	 q2.f++; n--; }break;
  case 2: while (n) {
	 if ( x.f <= *q2.l ) *q3.f++ = x.f; else *q3.f++ = *q2.l;
	 q2.l++; n--;}break;
  case 1: while (n) {
	 if ( x.f <= *q2.w ) *q3.f++ = x.f; else *q3.f++ = *q2.w;
	 q2.w++; n--;}break;
  case 0: while (n) {
	 if ( x.f <= *q2.b ) *q3.f++ = x.f; else *q3.f++ = *q2.b;
	 q2.b++; n--;}break;
  case 4: while (n) {
	 if ( x.f <= *q2.d ) *q3.d++ = x.f; else *q3.d++ = *q2.d;
	 q2.d++; n--;}break;
 }	break;
 case 2: x.l = *p1.l;
  switch (type2)	{
  case 2: while (n) {
	 if ( x.l <= *q2.l ) *q3.l++ = x.l; else *q3.l++ = *q2.l;
	 q2.l++; n--;}break;
  case 3: while (n) {
	 if ( x.l <= *q2.f ) *q3.f++ = x.l; else *q3.f++ = *q2.f;
	 q2.f++; n--; }break;
  case 1: while (n) {
	 if ( x.l <= *q2.w ) *q3.l++ = x.l; else *q3.l++ = *q2.w;
	 q2.w++; n--;}break;
  case 0: while (n) {
	 if ( x.l <= *q2.b ) *q3.l++ = x.l; else *q3.l++ = *q2.b;
	 q2.b++; n--;}break;
  case 4: while (n) {
	 if ( x.l <= *q2.d ) *q3.d++ = x.l; else *q3.d++ = *q2.d;
	 q2.d++; n--;}break;
 }	break;
 case 1: x.w = *p1.w;
  switch (type2)	{
  case 1: while (n) {
	 if ( x.w <= *q2.w ) *q3.w++ = x.w; else *q3.w++ = *q2.w;
	 q2.w++; n--;}break;
  case 3: while (n) {
	 if ( x.w <= *q2.f ) *q3.f++ = x.w; else *q3.f++ = *q2.f;
	 q2.f++; n--; }break;
  case 2: while (n) {
	 if ( x.w <= *q2.l ) *q3.l++ = x.w; else *q3.l++ = *q2.l;
	 q2.l++; n--;}break;
  case 0: while (n) {
	 if ( x.w <= *q2.b ) *q3.w++ = x.w; else *q3.w++ = *q2.b;
	 q2.b++; n--;}break;
  case 4: while (n) {
	 if ( x.w <= *q2.d ) *q3.d++ = x.w; else *q3.d++ = *q2.d;
	 q2.d++; n--;}break;
 }	break;
 case 0: x.b = *p1.b;
  switch (type2)	{
  case 0: while (n) {
	 if ( x.b <= *q2.b ) *q3.b++ = x.b; else *q3.b++ = *q2.b;
	 q2.b++; n--;}break;
  case 3: while (n) {
	 if ( x.b <= *q2.f ) *q3.f++ = x.b; else *q3.f++ = *q2.f;
	 q2.f++; n--; }break;
  case 2: while (n) {
	 if ( x.b <= *q2.l ) *q3.l++ = x.b; else *q3.l++ = *q2.l;
	 q2.l++; n--;}break;
  case 1: while (n) {
	 if ( x.b <= *q2.w ) *q3.w++ = x.b; else *q3.w++ = *q2.w;
	 q2.w++; n--;}break;
  case 4: while (n) {
	 if ( x.b <= *q2.d ) *q3.d++ = x.b; else *q3.d++ = *q2.d;
	 q2.d++; n--;}break;
 }	break;
 case 4:	x.d = *p1.d;
  switch (type2)	{
  case 4: while (n) {
	 if ( x.d <= *q2.d ) *q3.d++ = x.d; else *q3.d++ = *q2.d;
	 q2.d++; n--;}break;
  case 3: while (n) {
	 if ( x.d <= *q2.f ) *q3.d++ = x.d; else *q3.d++ = *q2.f;
	 q2.f++; n--; }break;
  case 2: while (n) {
	 if ( x.d <= *q2.l ) *q3.d++ = x.d; else *q3.d++ = *q2.l;
	 q2.l++; n--;}break;
  case 1: while (n) {
	 if ( x.d <= *q2.w ) *q3.d++ = x.d; else *q3.d++ = *q2.w;
	 q2.w++; n--;}break;
  case 0: while (n) {
	 if ( x.d <= *q2.b ) *q3.d++ = x.d; else *q3.d++ = *q2.b;
	 q2.b++; n--;}break;
 }	break;
 }
 return result_sym;
 }
 /*------------------------------------------------------------------------- */