t_forcetable make_gb_table(FILE *out,const output_env_t oenv,
                           const t_forcerec *fr,
                           const char *fn,
                           real rtab)
{
	const char *fns[3] = { "gbctab.xvg", "gbdtab.xvg", "gbrtab.xvg" };
	const char *fns14[3] = { "gbctab14.xvg", "gbdtab14.xvg", "gbrtab14.xvg" };
	FILE        *fp;
	t_tabledata *td;
	gmx_bool        bReadTab,bGenTab;
	real        x0,y0,yp;
	int         i,j,k,nx,nx0,tabsel[etiNR];
	void *      p_tmp;
	double      r,r2,Vtab,Ftab,expterm;
	
	t_forcetable table;
	
	double abs_error_r, abs_error_r2;
	double rel_error_r, rel_error_r2;
	double rel_error_r_old=0, rel_error_r2_old=0;
	double x0_r_error, x0_r2_error;
	
	
	/* Only set a Coulomb table for GB */
	/* 
	 tabsel[0]=etabGB;
	 tabsel[1]=-1;
	 tabsel[2]=-1;
	*/
	
	/* Set the table dimensions for GB, not really necessary to
	 * use etiNR (since we only have one table, but ...) 
	 */
	snew(td,1);
	table.r         = fr->gbtabr;
	table.scale     = fr->gbtabscale;
	table.scale_exp = 0;
	table.n         = table.scale*table.r;
	nx0             = 0;
	nx              = table.scale*table.r;
	
	/* Check whether we have to read or generate 
	 * We will always generate a table, so remove the read code
	 * (Compare with original make_table function
	 */
	bReadTab = FALSE;
	bGenTab  = TRUE;
	
	/* Each table type (e.g. coul,lj6,lj12) requires four 
	 * numbers per datapoint. For performance reasons we want
	 * the table data to be aligned to 16-byte. This is accomplished
	 * by allocating 16 bytes extra to a temporary pointer, and then
	 * calculating an aligned pointer. This new pointer must not be
	 * used in a free() call, but thankfully we're sloppy enough not
	 * to do this :-)
	 */
	
	/* 4 fp entries per table point, nx+1 points, and 16 bytes extra 
           to align it. */
	p_tmp = malloc(4*(nx+1)*sizeof(real)+16);
	
	/* align it - size_t has the same same as a pointer */
	table.tab = (real *) (((size_t) p_tmp + 16) & (~((size_t) 15)));  
	
	init_table(out,nx,nx0,table.scale,&(td[0]),!bReadTab);
	
	/* Local implementation so we don't have to use the etabGB
	 * enum above, which will cause problems later when
	 * making the other tables (right now even though we are using
	 * GB, the normal Coulomb tables will be created, but this
	 * will cause a problem since fr->eeltype==etabGB which will not
	 * be defined in fill_table and set_table_type
	 */
	
	for(i=nx0;i<nx;i++)
    {
		Vtab    = 0.0;
		Ftab    = 0.0;
		r       = td->x[i];
		r2      = r*r;
		expterm = exp(-0.25*r2);
		
		Vtab = 1/sqrt(r2+expterm);
		Ftab = (r-0.25*r*expterm)/((r2+expterm)*sqrt(r2+expterm));
		
		/* Convert to single precision when we store to mem */
		td->v[i]  = Vtab;
		td->f[i]  = Ftab;
		
    }
	
	copy2table(table.n,0,4,td[0].x,td[0].v,td[0].f,table.tab);
	
	if(bDebugMode())
    {
		fp=xvgropen(fns[0],fns[0],"r","V",oenv);
		/* plot the output 5 times denser than the table data */
		/* for(i=5*nx0;i<5*table.n;i++) */
		for(i=nx0;i<table.n;i++)
		{
			/* x0=i*table.r/(5*table.n); */
			x0=i*table.r/table.n;
			evaluate_table(table.tab,0,4,table.scale,x0,&y0,&yp);
			fprintf(fp,"%15.10e  %15.10e  %15.10e\n",x0,y0,yp);
			
		}
		gmx_fio_fclose(fp);
    }
	
	/*
	 for(i=100*nx0;i<99.81*table.n;i++)
	 {
	 r = i*table.r/(100*table.n);
	 r2      = r*r;
	 expterm = exp(-0.25*r2);
	 
	 Vtab = 1/sqrt(r2+expterm);
	 Ftab = (r-0.25*r*expterm)/((r2+expterm)*sqrt(r2+expterm));
	 
	 
	 evaluate_table(table.tab,0,4,table.scale,r,&y0,&yp);
	 printf("gb: i=%d, x0=%g, y0=%15.15f, Vtab=%15.15f, yp=%15.15f, Ftab=%15.15f\n",i,r, y0, Vtab, yp, Ftab);
	 
	 abs_error_r=fabs(y0-Vtab);
	 abs_error_r2=fabs(yp-(-1)*Ftab);
	 
	 rel_error_r=abs_error_r/y0;
	 rel_error_r2=fabs(abs_error_r2/yp);
	 
	 
	 if(rel_error_r>rel_error_r_old)
	 {
	 rel_error_r_old=rel_error_r;
	 x0_r_error=x0;
	 }
	 
	 if(rel_error_r2>rel_error_r2_old)
	 {
	 rel_error_r2_old=rel_error_r2;
	 x0_r2_error=x0;	
	 }
	 }
	 
	 printf("gb: MAX REL ERROR IN R=%15.15f, MAX REL ERROR IN R2=%15.15f\n",rel_error_r_old, rel_error_r2_old);
	 printf("gb: XO_R=%g, X0_R2=%g\n",x0_r_error, x0_r2_error);
	 
	 exit(1); */
	done_tabledata(&(td[0]));
	sfree(td);
	
	return table;
	
	
}
t_forcetable make_tables(FILE *out,const output_env_t oenv,
                         const t_forcerec *fr,
			 gmx_bool bVerbose,const char *fn,
			 real rtab,int flags)
{
  const char *fns[3] = { "ctab.xvg", "dtab.xvg", "rtab.xvg" };
  const char *fns14[3] = { "ctab14.xvg", "dtab14.xvg", "rtab14.xvg" };
  FILE        *fp;
  t_tabledata *td;
  gmx_bool        b14only,bReadTab,bGenTab;
  real        x0,y0,yp;
  int         i,j,k,nx,nx0,tabsel[etiNR];
  
  t_forcetable table;

  b14only = (flags & GMX_MAKETABLES_14ONLY);

  if (flags & GMX_MAKETABLES_FORCEUSER) {
    tabsel[etiCOUL] = etabUSER;
    tabsel[etiLJ6]  = etabUSER;
    tabsel[etiLJ12] = etabUSER;
  } else {
    set_table_type(tabsel,fr,b14only);
  }
  snew(td,etiNR);
  table.r         = rtab;
  table.scale     = 0;
  table.n         = 0;
  table.scale_exp = 0;
  nx0             = 10;
  nx              = 0;
  
  /* Check whether we have to read or generate */
  bReadTab = FALSE;
  bGenTab  = FALSE;
  for(i=0; (i<etiNR); i++) {
    if (ETAB_USER(tabsel[i]))
      bReadTab = TRUE;
    if (tabsel[i] != etabUSER)
      bGenTab  = TRUE;
  }
  if (bReadTab) {
    read_tables(out,fn,etiNR,0,td);
    if (rtab == 0 || (flags & GMX_MAKETABLES_14ONLY)) {
      rtab      = td[0].x[td[0].nx-1];
      table.n   = td[0].nx;
      nx        = table.n;
    } else {
      if (td[0].x[td[0].nx-1] < rtab) 
	gmx_fatal(FARGS,"Tables in file %s not long enough for cut-off:\n"
		  "\tshould be at least %f nm\n",fn,rtab);
      nx        = table.n = (int)(rtab*td[0].tabscale + 0.5);
    }
    table.scale = td[0].tabscale;
    nx0         = td[0].nx0;
  }
  if (bGenTab) {
    if (!bReadTab) {
#ifdef GMX_DOUBLE
      table.scale = 2000.0;
#else
      table.scale = 500.0;
#endif
      nx = table.n = rtab*table.scale;
    }
  }
  if (fr->bBHAM) {
    if(fr->bham_b_max!=0)
      table.scale_exp = table.scale/fr->bham_b_max;
    else
      table.scale_exp = table.scale;
  }

  /* Each table type (e.g. coul,lj6,lj12) requires four 
   * numbers per nx+1 data points. For performance reasons we want
   * the table data to be aligned to 16-byte.
   */
  snew_aligned(table.tab, 12*(nx+1)*sizeof(real),16);

  for(k=0; (k<etiNR); k++) {
    if (tabsel[k] != etabUSER) {
      init_table(out,nx,nx0,
		 (tabsel[k] == etabEXPMIN) ? table.scale_exp : table.scale,
		 &(td[k]),!bReadTab);
      fill_table(&(td[k]),tabsel[k],fr);
      if (out) 
	fprintf(out,"%s table with %d data points for %s%s.\n"
		"Tabscale = %g points/nm\n",
		ETAB_USER(tabsel[k]) ? "Modified" : "Generated",
		td[k].nx,b14only?"1-4 ":"",tprops[tabsel[k]].name,
		td[k].tabscale);
    }
    copy2table(table.n,k*4,12,td[k].x,td[k].v,td[k].f,table.tab);
    
    if (bDebugMode() && bVerbose) {
      if (b14only)
	fp=xvgropen(fns14[k],fns14[k],"r","V",oenv);
      else
	fp=xvgropen(fns[k],fns[k],"r","V",oenv);
      /* plot the output 5 times denser than the table data */
      for(i=5*((nx0+1)/2); i<5*table.n; i++) {
	x0 = i*table.r/(5*(table.n-1));
	evaluate_table(table.tab,4*k,12,table.scale,x0,&y0,&yp);
	fprintf(fp,"%15.10e  %15.10e  %15.10e\n",x0,y0,yp);
      }
      gmx_fio_fclose(fp);
    }
    done_tabledata(&(td[k]));
  }
  sfree(td);

  return table;
}
Exemple #3
0
t_forcetable make_tables(FILE *out,const output_env_t oenv,
                         const t_forcerec *fr,
			 gmx_bool bVerbose,const char *fn,
			 real rtab,int flags)
{
  const char *fns[3] = { "ctab.xvg", "dtab.xvg", "rtab.xvg" };
  const char *fns14[3] = { "ctab14.xvg", "dtab14.xvg", "rtab14.xvg" };
  FILE        *fp;
  t_tabledata *td;
  gmx_bool        b14only,bReadTab,bGenTab;
  real        x0,y0,yp;
  int         i,j,k,nx,nx0,tabsel[etiNR];
  real        scalefactor;

  t_forcetable table;

  b14only = (flags & GMX_MAKETABLES_14ONLY);

  if (flags & GMX_MAKETABLES_FORCEUSER) {
    tabsel[etiCOUL] = etabUSER;
    tabsel[etiLJ6]  = etabUSER;
    tabsel[etiLJ12] = etabUSER;
  } else {
    set_table_type(tabsel,fr,b14only);
  }
  snew(td,etiNR);
  table.r         = rtab;
  table.scale     = 0;
  table.n         = 0;
  table.scale_exp = 0;
  nx0             = 10;
  nx              = 0;
  
  table.interaction   = GMX_TABLE_INTERACTION_ELEC_VDWREP_VDWDISP;
  table.format        = GMX_TABLE_FORMAT_CUBICSPLINE_YFGH;
  table.formatsize    = 4;
  table.ninteractions = 3;
  table.stride        = table.formatsize*table.ninteractions;

  /* Check whether we have to read or generate */
  bReadTab = FALSE;
  bGenTab  = FALSE;
  for(i=0; (i<etiNR); i++) {
    if (ETAB_USER(tabsel[i]))
      bReadTab = TRUE;
    if (tabsel[i] != etabUSER)
      bGenTab  = TRUE;
  }
  if (bReadTab) {
    read_tables(out,fn,etiNR,0,td);
    if (rtab == 0 || (flags & GMX_MAKETABLES_14ONLY)) {
      rtab      = td[0].x[td[0].nx-1];
      table.n   = td[0].nx;
      nx        = table.n;
    } else {
      if (td[0].x[td[0].nx-1] < rtab) 
	gmx_fatal(FARGS,"Tables in file %s not long enough for cut-off:\n"
		  "\tshould be at least %f nm\n",fn,rtab);
      nx        = table.n = (int)(rtab*td[0].tabscale + 0.5);
    }
    table.scale = td[0].tabscale;
    nx0         = td[0].nx0;
  }
  if (bGenTab) {
    if (!bReadTab) {
#ifdef GMX_DOUBLE
      table.scale = 2000.0;
#else
      table.scale = 500.0;
#endif
      nx = table.n = rtab*table.scale;
    }
  }
  if (fr->bBHAM) {
    if(fr->bham_b_max!=0)
      table.scale_exp = table.scale/fr->bham_b_max;
    else
      table.scale_exp = table.scale;
  }

  /* Each table type (e.g. coul,lj6,lj12) requires four 
   * numbers per nx+1 data points. For performance reasons we want
   * the table data to be aligned to 16-byte.
   */
  snew_aligned(table.data, 12*(nx+1)*sizeof(real),16);

  for(k=0; (k<etiNR); k++) {
    if (tabsel[k] != etabUSER) {
      init_table(out,nx,nx0,
		 (tabsel[k] == etabEXPMIN) ? table.scale_exp : table.scale,
		 &(td[k]),!bReadTab);
      fill_table(&(td[k]),tabsel[k],fr);
      if (out) 
	fprintf(out,"%s table with %d data points for %s%s.\n"
		"Tabscale = %g points/nm\n",
		ETAB_USER(tabsel[k]) ? "Modified" : "Generated",
		td[k].nx,b14only?"1-4 ":"",tprops[tabsel[k]].name,
		td[k].tabscale);
    }

    /* Set scalefactor for c6/c12 tables. This is because we save flops in the non-table kernels
     * by including the derivative constants (6.0 or 12.0) in the parameters, since
     * we no longer calculate force in most steps. This means the c6/c12 parameters
     * have been scaled up, so we need to scale down the table interactions too.
     * It comes here since we need to scale user tables too.
     */
      if(k==etiLJ6)
      {
          scalefactor = 1.0/6.0;
      }
      else if(k==etiLJ12 && tabsel[k]!=etabEXPMIN)
      {
          scalefactor = 1.0/12.0;
      }
      else
      {
          scalefactor = 1.0;
      }

    copy2table(table.n,k*4,12,td[k].x,td[k].v,td[k].f,scalefactor,table.data);
    
    if (bDebugMode() && bVerbose) {
      if (b14only)
	fp=xvgropen(fns14[k],fns14[k],"r","V",oenv);
      else
	fp=xvgropen(fns[k],fns[k],"r","V",oenv);
      /* plot the output 5 times denser than the table data */
      for(i=5*((nx0+1)/2); i<5*table.n; i++) {
	x0 = i*table.r/(5*(table.n-1));
	evaluate_table(table.data,4*k,12,table.scale,x0,&y0,&yp);
	fprintf(fp,"%15.10e  %15.10e  %15.10e\n",x0,y0,yp);
      }
      gmx_fio_fclose(fp);
    }
    done_tabledata(&(td[k]));
  }
  sfree(td);

  return table;
}
Exemple #4
0
t_forcetable make_atf_table(FILE *out,const output_env_t oenv,
			    const t_forcerec *fr,
			    const char *fn,
                            matrix box)
{
	const char *fns[3] = { "tf_tab.xvg", "atfdtab.xvg", "atfrtab.xvg" };
	FILE        *fp;
	t_tabledata *td;
	real        x0,y0,yp,rtab;
	int         i,nx,nx0;
	void *      p_tmp;
        real        rx, ry, rz, box_r;
	
	t_forcetable table;
	
	
	/* Set the table dimensions for ATF, not really necessary to
	 * use etiNR (since we only have one table, but ...) 
	 */
	snew(td,1);
        
        if (fr->adress_type == eAdressSphere){
            /* take half box diagonal direction as tab range */
               rx = 0.5*box[0][0]+0.5*box[1][0]+0.5*box[2][0];
               ry = 0.5*box[0][1]+0.5*box[1][1]+0.5*box[2][1];
               rz = 0.5*box[0][2]+0.5*box[1][2]+0.5*box[2][2];
               box_r = sqrt(rx*rx+ry*ry+rz*rz);
               
        }else{
            /* xsplit: take half box x direction as tab range */
               box_r        = box[0][0]/2;
        }
        table.r         = box_r;
	table.scale     = 0;
	table.n         = 0;
	table.scale_exp = 0;
	nx0             = 10;
	nx              = 0;
	
        read_tables(out,fn,1,0,td);
        rtab      = td[0].x[td[0].nx-1];

       if (fr->adress_type == eAdressXSplit && (rtab < box[0][0]/2)){
           gmx_fatal(FARGS,"AdResS full box therm force table in file %s extends to %f:\n"
                        "\tshould extend to at least half the length of the box in x-direction"
                        "%f\n",fn,rtab, box[0][0]/2);
       }
       if (rtab < box_r){
               gmx_fatal(FARGS,"AdResS full box therm force table in file %s extends to %f:\n"
                "\tshould extend to at least for spherical adress"
                "%f (=distance from center to furthermost point in box \n",fn,rtab, box_r);
       }


        table.n   = td[0].nx;
        nx        = table.n;
        table.scale = td[0].tabscale;
        nx0         = td[0].nx0;

	/* Each table type (e.g. coul,lj6,lj12) requires four 
	 * numbers per datapoint. For performance reasons we want
	 * the table data to be aligned to 16-byte. This is accomplished
	 * by allocating 16 bytes extra to a temporary pointer, and then
	 * calculating an aligned pointer. This new pointer must not be
	 * used in a free() call, but thankfully we're sloppy enough not
	 * to do this :-)
	 */
	
	/* 4 fp entries per table point, nx+1 points, and 16 bytes extra 
           to align it. */
       p_tmp = malloc(4*(nx+1)*sizeof(real)+16);
	
	/* align it - size_t has the same same as a pointer */
	table.tab = (real *) (((size_t) p_tmp + 16) & (~((size_t) 15)));
	
	copy2table(table.n,0,4,td[0].x,td[0].v,td[0].f,table.tab);
	
	if(bDebugMode())
	  {
	    fp=xvgropen(fns[0],fns[0],"r","V",oenv);
	    /* plot the output 5 times denser than the table data */
	    /* for(i=5*nx0;i<5*table.n;i++) */
	   
            for(i=5*((nx0+1)/2); i<5*table.n; i++)
	      {
		/* x0=i*table.r/(5*table.n); */
		x0 = i*table.r/(5*(table.n-1));
		evaluate_table(table.tab,0,4,table.scale,x0,&y0,&yp);
		fprintf(fp,"%15.10e  %15.10e  %15.10e\n",x0,y0,yp);
		
	      }
	    ffclose(fp);
	  }

	done_tabledata(&(td[0]));
	sfree(td);
	
	return table;
}
tree
evaluate_impl (tree t) {
  //cout << "Really evaluate " << t << LF;
  switch (L(t)) {
  /* Typesetting primitives with side effects */
  case DATOMS:
    return evaluate_formatting (t, ATOM_DECORATIONS);
  case DLINES:
    return evaluate_formatting (t, LINE_DECORATIONS);
  case DPAGES:
    return evaluate_formatting (t, PAGE_DECORATIONS);
  case TFORMAT:
    return evaluate_formatting (t, CELL_FORMAT);
  case TABLE:
    return evaluate_table (t);

  /* Primitives for macro expansion */
  case ASSIGN:
    return evaluate_assign (t);
  case WITH:
    return evaluate_with (t);
  case PROVIDES:
    return evaluate_provides (t);
  case VALUE:
    return evaluate_value (t);
  case QUOTE_VALUE:
    return evaluate_quote_value (t);
  case MACRO:
    return copy (t);
  case DRD_PROPS:
    return evaluate_drd_props (t);
#ifdef CLASSICAL_MACRO_EXPANSION
  case ARG:
    return evaluate_arg (t);
  case QUOTE_ARG:
    return evaluate_quote_arg (t);
#endif
  case COMPOUND:
    return evaluate_compound (t);
  case XMACRO:
    return copy (t);
  case GET_LABEL:
    return evaluate_get_label (t);
  case GET_ARITY:
    return evaluate_get_arity (t);

  /* Primitives for quoting and evaluation */
  case MAP_ARGS:
    return evaluate_rewrite (t);
  case EVAL_ARGS:
    return evaluate_eval_args (t);
  case MARK:
    return tree (MARK, copy (t[0]), evaluate (t[1]));
  case EXPAND_AS:
    return evaluate (t[1]);
  case EVAL:
    return evaluate (evaluate (t[0]));
  case QUOTE:
    return t[0];
  case QUASI:
    return evaluate (evaluate_quasiquote (t[0]));
  case QUASIQUOTE:
    return evaluate_quasiquote (t[0]);
  case UNQUOTE:
  case VAR_UNQUOTE:
    return evaluate (t[0]);
  case COPY:
    return copy (evaluate (t[0]));    

  /* Control structures */
  case IF:
  case VAR_IF:
    return evaluate_if (t);
  case CASE:
    return evaluate_case (t);
  case WHILE:
    return evaluate_while (t);
  case FOR_EACH:
    return evaluate_for_each (t);
  case EXTERN:
    return evaluate_rewrite (t);
  case VAR_INCLUDE:
    return evaluate_include (t);
  case WITH_PACKAGE:
    return evaluate_rewrite (t);
  case USE_PACKAGE:
    return evaluate_use_package (t);
  case USE_MODULE:
    return evaluate_use_module (t);

  /* Computational markup */
  case OR:
    return evaluate_or (t);
  case XOR:
    return evaluate_xor (t);
  case AND:
    return evaluate_and (t);
  case NOT:
    return evaluate_not (t);
  case PLUS:
  case MINUS:
    return evaluate_plus_minus (t);
  case TIMES:
  case OVER:
    return evaluate_times_over (t);
  case DIV:
    return evaluate_divide (t);
  case MOD:
    return evaluate_modulo (t);
  case MATH_SQRT:
    return evaluate_math_sqrt (t);
  case EXP:
    return evaluate_exp (t);
  case LOG:
    return evaluate_log (t);
  case POW:
    return evaluate_pow (t);
  case COS:
    return evaluate_cos (t);
  case SIN:
    return evaluate_sin (t);
  case TAN:
    return evaluate_tan (t);
  case MERGE:
    return evaluate_merge (t);
  case LENGTH:
    return evaluate_length (t);
  case RANGE:
    return evaluate_range (t);
  case NUMBER:
    return evaluate_number (t);
  case _DATE:
    return evaluate_date (t);
  case TRANSLATE:
    return evaluate_translate (t);
  case CHANGE_CASE:
    return evaluate_change_case (t);
  case FIND_FILE:
    return evaluate_find_file (t);
  case IS_TUPLE:
    return evaluate_is_tuple (t);
  case LOOK_UP:
    return evaluate_lookup (t);
  case EQUAL:
    return evaluate_equal (t);
  case UNEQUAL:
    return evaluate_unequal (t);
  case LESS:
    return evaluate_less (t);
  case LESSEQ:
    return evaluate_lesseq (t);
  case GREATER:
    return evaluate_greater (t);
  case GREATEREQ:
    return evaluate_greatereq (t);
  case BLEND:
    return evaluate_blend (t);

  /* Length units */
  case CM_LENGTH:
    return evaluate_cm_length ();
  case MM_LENGTH:
    return evaluate_mm_length ();
  case IN_LENGTH:
    return evaluate_in_length ();
  case PT_LENGTH:
    return evaluate_pt_length ();
  case BP_LENGTH:
    return evaluate_bp_length ();
  case DD_LENGTH:
    return evaluate_dd_length ();
  case PC_LENGTH:
    return evaluate_pc_length ();
  case CC_LENGTH:
    return evaluate_cc_length ();
  case FS_LENGTH:
    return evaluate_fs_length ();
  case FBS_LENGTH:
    return evaluate_fbs_length ();
  case EM_LENGTH:
    return evaluate_em_length ();
  case LN_LENGTH:
    return evaluate_ln_length ();
  case SEP_LENGTH:
    return evaluate_sep_length ();
  case YFRAC_LENGTH:
    return evaluate_yfrac_length ();
  case EX_LENGTH:
    return evaluate_ex_length ();
  case FN_LENGTH:
    return evaluate_fn_length ();
  case FNS_LENGTH:
    return evaluate_fns_length ();
  case BLS_LENGTH:
    return evaluate_bls_length ();
  case FNBOT_LENGTH:
    return evaluate_fnbot_length ();
  case FNTOP_LENGTH:
    return evaluate_fntop_length ();
  case SPC_LENGTH:
    return evaluate_spc_length ();
  case XSPC_LENGTH:
    return evaluate_xspc_length ();
  case PAR_LENGTH:
    return evaluate_par_length ();
  case PAG_LENGTH:
    return evaluate_pag_length ();
  case GW_LENGTH:
    return evaluate_gw_length ();
  case GH_LENGTH:
    return evaluate_gh_length ();
  case GU_LENGTH:
    return evaluate_gu_length ();
  case TMPT_LENGTH:
    return evaluate_tmpt_length ();
  case PX_LENGTH:
    return evaluate_px_length ();
  case MSEC_LENGTH:
    return evaluate_msec_length ();
  case SEC_LENGTH:
    return evaluate_sec_length ();
  case MIN_LENGTH:
    return evaluate_min_length ();
  case HR_LENGTH:
    return evaluate_hr_length ();

  /* Primitives for stylesheet editing */
  case STYLE_WITH:
  case VAR_STYLE_WITH:
    return evaluate (t[N(t)-1]);
  case STYLE_ONLY:
  case VAR_STYLE_ONLY:
  case ACTIVE:
  case VAR_ACTIVE:
  case INACTIVE:
  case VAR_INACTIVE:
    return evaluate_compound (t);
  case REWRITE_INACTIVE:
    return evaluate_rewrite (t);

  /* Linking primitives */
  case HARD_ID:
    return evaluate_hard_id (t[0]);
  case SCRIPT:
    return evaluate_script (t);
  case HLINK:
  case ACTION:
    return evaluate_compound (t);
  case SET_BINDING:
    return evaluate_set_binding (t);
  case GET_BINDING:
    return evaluate_get_binding (t);

  /* Graphical primitives */
  case PATTERN:
    return evaluate_pattern (t);
  case _POINT:
    return evaluate_point (t);
    /*
  case BOX_INFO:
    return evaluate_box_info (t);
  case FRAME_DIRECT:
    return evaluate_frame_direct (t);
  case FRAME_INVERSE:
    return evaluate_frame_inverse (t);
    */

  /* User extensions */
  default:
    if (L(t) < START_EXTENSIONS) {
      int i, n= N(t);
      tree r (t, n);
      for (i=0; i<n; i++)
	r[i]= evaluate (t[i]);
      transfer_ip (t, r);
      return r;
    }
    else {
      tree r= evaluate_compound (t);
      return r;
    }      
  }
}