[BACK]Return to call_phc.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / PHC / C

File: [local] / OpenXM_contrib / PHC / C / call_phc.c (download)

Revision 1.1.1.1 (vendor branch), Sun Oct 29 17:45:34 2000 UTC (23 years, 6 months ago) by maekawa
Branch: PHC, MAIN
CVS Tags: v2, maekawa-ipv6, RELEASE_1_2_3, RELEASE_1_2_2_KNOPPIX_b, RELEASE_1_2_2_KNOPPIX, RELEASE_1_2_2, RELEASE_1_2_1, HEAD
Changes since 1.1: +0 -0 lines

Import the second public release of PHCpack.

OKed by Jan Verschelde.

/* This is a simple C interface to the black-box solver of phc,
** written by Nobuki Takayama.
** Requirements:
**  1) executable version of phc must be on /tmp;
**  2) user of this program has write permissions to create
**     the files "input" and "output" in the directory where
**     this program is executed.
*/

#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>

/* Definition of class identifiers. */
#define SstringObject     5
#define Sarray            6  

/* Definition of Object */
union cell {
  int ival;
  char *str;
  struct object *op;
};
struct object{
  int tag;                /* class identifier */
  union cell lc;          /* left cell */
  union cell rc;          /* right cell */
};

/* Memory allocation function.  
   I recommend not to use malloc and to use gc4.14 for large applications. */
#define sGC_malloc(n)   malloc(n)

/********** macros to use Sarray **************/
/* put to Object Array */
#define phc_putoa(ob,i,cc) {\
if ((ob).tag != Sarray) {fprintf(stderr,"Warning: PUTOA is for an array of objects\n");} else \
{if ((0 <= (i)) && ((i) < (ob).lc.ival)) {\
  (ob.rc.op)[i] = cc;\
}else{\
  fprintf(stderr,"Warning: PUTOA, the size is %d.\n",(ob).lc.ival);\
}}}
#define phc_getoa(ob,i) ((ob.rc.op)[i])
#define phc_getoaSize(ob) ((ob).lc.ival)


/* prototypes */
struct object phc_newObjectArray(int size);
void phc_printObject(FILE *fp,struct object ob);
char *phc_generateUniqueFileName(char *s);
struct object phc_complexTo(long double r, long double i);
struct object phc_longdoubleToStringObject(long double r);

int phc_scan_for_string(FILE *fp, char str[], int lenstr);
struct object phc_scan_solutions(FILE *fp, int npaths, int dim );
struct object phc_scan_output_of_phc(char *fname);
struct object phc_call_phc(char *sys); 

main() {
  struct object ob;
  ob = phc_call_phc("2\n x**2 + y**2 - 1;\n x**2 + y**2 - 8*x - 3;\n");
  printf("-----------------------------------------------------------\n");
  phc_printObject(stdout,ob);
  printf("\n");
}

int phc_scan_for_string(FILE *fp, char str[], int lenstr)
     /*
  **  Scans the file fp for a certain string str of length lenstr+1.
  **  Reading stops when the string has been found, then the variable
  **  on return equals 1, otherwise 0 is returned.
  */
{
  char buf[lenstr+1];
  char ch;
  int index,i,compare,npaths,dim,found;
  index = -1;
  found = 0;
  while ((fscanf(fp,"%c",&ch)!=EOF) && found == 0)
    {
      if (index == -1 && ch == str[0])
	{
	  index = 0;
	  buf[index] = ch;
	}
      else
	{
	  if (index == lenstr)
	    {
	      compare = 0;
	      for (i=0; i<lenstr+1; i++)
		{
		  if (buf[i]!=str[i])
		    {
		      compare = compare+1;
		    }
		}
	      if (compare == 0)
		{
		  found = 1;
		}
	      index = -1;
	    }
	  else
	    if (index > -1 && index < lenstr)
	      {
		index = index+1;
		buf[index] = ch;
	      }
	}
      if (found == 1) break;
    }
  return found;
}
struct object phc_scan_solutions(FILE *fp, int npaths, int dim )
     /*
  **  Scans the file for the solutions, from a list of length npaths,
  **  of complex vectors with dim entries.
  **  The tolerance for the residual to a solution is set to 1.0E-12.
  **  Returns the number of solutions.
  */
{
  struct object rob,sob;
  char ch;
  int fnd,i,j,nsols;
  float res;
  long double realpart;
  long double imagpart;
  long double realparts[npaths][dim];
  long double imagparts[npaths][dim];
  nsols = 0;
  while (fscanf(fp,"%c",&ch)!=EOF) 
    {
      fnd = phc_scan_for_string(fp,"start residual :",15);
      if (fnd==1)
	{
	  fscanf(fp,"%E",&res);
	  /* printf(" residual = "); printf("%E\n",res); */
	  if (res < 1.0E-12) nsols = nsols+1;
	  fnd = phc_scan_for_string(fp,"the solution for t :",19);
	  for (i=0;i<dim;i++)
	    {
	      fnd = phc_scan_for_string(fp,":",0);
	      fscanf(fp,"%LE",&realpart);
	      fscanf(fp,"%LE",&imagpart);
	      if (res < 1.0E-12)
		{
		  realparts[nsols-1][i] = realpart;
		  imagparts[nsols-1][i] = imagpart;
		}
	    }
	}
    }
  /* fprintf(stderr,"  number of solutions = %i\n",nsols); */
  rob = phc_newObjectArray(nsols);
  for (i=0;i<nsols;i++)
    {
      /* fprintf(stderr,"Solution %i :\n",i+1); */
      sob = phc_newObjectArray(dim);
      for (j=0;j<dim;j++)
	{
	  /*
	  printf("%20.14LE",realparts[i][j]); printf("  ");
	  printf("%20.14LE",imagparts[i][j]); printf("\n");
	  */
	  phc_putoa(sob,j,phc_complexTo(realparts[i][j],imagparts[i][j]));
	}
      phc_putoa(rob,i,sob);
    }
  return(rob);
}
struct object phc_scan_output_of_phc(char *fname)
     /*
  **  Scans the file "output" of phc in two stages to get
  **   1) the number of paths and the dimension;
  **   2) the solutions, vectors with residuals < 1.0E-12.
  */
{
  FILE *otp;
  char ch;
  int fnd,npaths,dim,i,nsols;
  otp = fopen(fname,"r");
  fprintf(stderr,"Scanning the %s of phc.\n",fname);
  fnd = phc_scan_for_string(otp,"THE SOLUTIONS :",14);
  fscanf(otp,"%i",&npaths);
  fprintf(stderr,"  number of paths traced = %i\n",npaths);
  fscanf(otp,"%i",&dim);
  fprintf(stderr,"  dimension of solutions = %i\n",dim);
  return(phc_scan_solutions(otp,npaths,dim));
}
struct object phc_call_phc(char *sys)  /* call phc, system as string */
{
  FILE *inp;
  char *f,*outf;
  char cmd[1024];
  f = phc_generateUniqueFileName("tmp.input");
  outf = phc_generateUniqueFileName("tmp.output");
  fprintf(stderr,"Creating file with name %s.\n",f);
  inp = fopen(f,"w");
  fprintf(inp,sys);
  fclose(inp);
  sprintf(cmd,"/tmp/phc -b %s %s",f,outf);
  fprintf(stderr,"Calling %s, black-box solver of phc.\n",cmd);
  system(cmd);
  fprintf(stderr,"See the file %s for results.\n",outf);
  return(phc_scan_output_of_phc(outf));
}


struct object phc_newObjectArray(size) 
int size;
{
  struct object rob;
  struct object *op;
  if (size > 0) {
    op = (struct object *)sGC_malloc(size*sizeof(struct object));
    if (op == (struct object *)NULL) {fprintf(stderr,"No memory\n");exit(1);}
  }else{
    op = (struct object *)NULL;
  }
  rob.tag = Sarray;
  rob.lc.ival = size;
  rob.rc.op = op;
  return(rob);
}

void phc_printObject(FILE *fp,struct object ob)
{
  int n,i;
  if (ob.tag == SstringObject) {
    fprintf(fp,"%s",ob.lc.str);
  }else if (ob.tag == Sarray) {
    n = phc_getoaSize(ob);
    fprintf(fp,"[");
    for (i=0; i<n; i++) {
      phc_printObject(fp,phc_getoa(ob,i));
      if (i <n-1) fprintf(fp,", ");
    }
    fprintf(fp,"]");
  }else{
    fprintf(stderr,"Unknown object tag %d",ob.tag);
  }
}
    

char *phc_generateUniqueFileName(char *s)
{
  char *t;
  int i;
  struct stat statbuf;
  t = (char *)sGC_malloc(sizeof(char)*strlen(s)+4+2);
  for (i=0; i<1000; i++) {
    /* Give up if we failed for 1000 names. */
    sprintf(t,"%s.%d",s,i);
    if (stat(t,&statbuf) < 0) {
      return(t);
    }
  }
  fprintf(stderr,"Could not generate a unique file name.");
  return(NULL);
}

struct object phc_longdoubleToStringObject(long double r)
{
  struct object rob;
  rob.tag = SstringObject;
  rob.lc.str = (char *) sGC_malloc(sizeof(char)*50); /*??*/
  sprintf(rob.lc.str,"%20.14LE",r);
  return(rob);
}
   
struct object phc_complexTo(long double r, long double i)
{
  struct object rob;
  rob = phc_newObjectArray(2);
  phc_putoa(rob,0,phc_longdoubleToStringObject(r));
  phc_putoa(rob,1,phc_longdoubleToStringObject(i));
  return(rob);
}