/* 
   * Copyright (C) 1997, Alexander Pukhov 
   * Copyright (C) 2001-2003, CompHEP Collaboration
   *------------------------------------------------------
   * $Id: math_out.c,v 1.4 2003/06/25 18:46:42 kryukov Exp $
   *
   * $Log: math_out.c,v $
   * Revision 1.4  2003/06/25 18:46:42  kryukov
   * *** empty log message ***
   *
   * Revision 1.3  2003/04/22 09:01:21  kryukov
   * Apply indent to improve readability of files
   *
   * Revision 1.2  2003/04/20 17:55:03  kryukov
   * Clean up warnings during make
   *
 */
#include "getmem/include/getmem.h"
#include "chep_crt/include/chep_crt.h"
#include "service2/include/os.h"

#include "symb/include/syst2.h"
#include "symb/include/physics.h"
#include "symb/include/s_files.h"
#include "symb/include/procvar.h"
#include "symb/include/out_serv.h"
#include "symb/include/saveres.h"
#include "symb/include/process.h"
#include "symb/include/math_out.h"


static void 
writeprocessname (int *prtclNum)
{
  int i;

  writeF ("  process  ");
  for (i = 1; i <= nin; i++)
    {
      writeF ("%s(p%d)", prtclbase[prtclNum[i] - 1].name, i);
      if (i < nin)
	writeF ("+");
      else
	writeF ("->");
    }

  for (i = nin + 1; i <= nin + nout; i++)
    {
      writeF ("%s(p%d)", prtclbase[prtclNum[i] - 1].name, i);
      if (i < nin + nout)
	writeF ("+");
      else
	writeF ("\n");
    }
}


static void 
emitprocessname (int *prtclNum)
{
  int i;

  writeF ("inParticles = {");
  for (i = 1; i <= nin; i++)
    {
      writeF ("\"%s\"", prtclbase[prtclNum[i] - 1].name);
      if (i < nin)
	writeF (",");
      else
	writeF ("}\n");
    }

  writeF ("outParticles = {");

  for (i = nin + 1; i <= nin + nout; i++)
    {
      writeF ("\"%s\"", prtclbase[prtclNum[i] - 1].name);
      if (i < nin + nout)
	writeF (",");
      else
	writeF ("}\n");
    }

}



static void 
emitexpression (catrec * cr)
{
  int i;

  seekArchiv (cr->factpos);
  readvardef ();
  writeF ("totFactor = ((");
  rewritepolynom ();
  writeF (")/(");
  rewritepolynom ();
  writeF ("));");
  writeF ("\n");
  clearvardef ();

  seekArchiv (cr->rnumpos);

  readvardef ();
  writeF ("numerator =(");
  rewritepolynom ();
  writeF (");\n");
  clearvardef ();
  seekArchiv (cr->denompos);
  readDenominators ();

  writeF ("denominator =");
  for (i = 0; i < denrno; i++)
    {
      char momStr[20];
      if (i)
	writeF ("*");
      else
	writeF ("(");
      momentToString (denom[i].momStr, momStr);
      writeF ("propDen[%s,%s,%s]", momStr, vararr[denom[i].mass].alias,
	      vararr[denom[i].width].alias);
      if (denom[i].power > 1)
	writeF ("^%d", denom[i].power);
    }
  if (i)
    writeF (");\n");
  else
    writeF ("1;\n");
}

static void 
modifyFunc (char *lch)
{
  int c;
  lch[0] = toupper (lch[0]);
  while (lch[0] != '(')
    lch++;
  lch[0] = '[';
  for (c = 1, lch++; c; lch++)
    if (lch[0] == ')')
      c--;
    else if (lch[0] == '(')
      c++;
  lch[-1] = ']';
}


static void 
writeparameters (int nsub)
{
  int k = 0;
  int first = 1;
  char s[STRSIZ];
  char *lch;

  writeF ("\n");
  writeF ("parameters={\n");

  for (k = 1; k <= nmodelvar; k++)
    {
      if (vararr[k].used && !modelvars[k].func)
	{
	  if (first)
	    {
	      first = 0;
	      writeF (" ");
	    }
	  else
	    writeF (",");
	  writeF ("%s -> ", vararr[k].alias);
	  sprintf (s, "%17.11E", vararr[k].tmpvalue);
	  lch = strchr (s, 'E');
	  if (lch)
	    {
	      int d;
	      sscanf (lch + 1, "%d", &d);
	      sprintf (lch, "*10^(%d)", d);
	    }
	  writeF ("%s\n", s);
	}
    }

  writeF ("           };\n");
  writeF ("\n");
  first = 1;
  writeF ("substitutions={\n");

  for (k = nmodelvar; k; k--)
    {
      if (vararr[k].used && modelvars[k].func)
	{
	  sscanf (modelvars[k].func, "%[^|]", s);
	  trim (s);

	  while ((lch = strstr (s, "sqrt(")))
	    modifyFunc (lch);
	  while ((lch = strstr (s, "sin(")))
	    modifyFunc (lch);
	  while ((lch = strstr (s, "cos(")))
	    modifyFunc (lch);
	  while ((lch = strstr (s, "tan(")))
	    modifyFunc (lch);
	  while ((lch = strstr (s, "asin(")))
	    modifyFunc (lch);
	  while ((lch = strstr (s, "acos(")))
	    modifyFunc (lch);
	  while ((lch = strstr (s, "atan(")))
	    modifyFunc (lch);
	  while ((lch = strstr (s, "exp(")))
	    modifyFunc (lch);
	  while ((lch = strstr (s, "log(")))
	    modifyFunc (lch);

	  if (first)
	    {
	      first = 0;
	      writeF (" ");
	    }
	  else
	    writeF (",");
	  writeF ("%s->%s", vararr[k].alias, s);
	  writeF ("\n");
	}
    }
  writeF ("              };\n");
}


static void 
startMath (int nsub, int *prtclNum, int ncalc)
{
  char f_name[STRSIZ];
  outputLanguage = 'M';
  initvararray (nsub, outputLanguage);

  sprintf (f_name, "%sresults%csymb%d.m", pathtouser, f_slash, nsub);
  outFileOpen (f_name);

  writeF ("(*\n");
  writeLabel (' ');
  writeprocessname (prtclNum);
  writeF ("*)\n");
  writeparameters (nsub);
  writeF ("\n");
  emitprocessname (prtclNum);
  writeF ("\n");
  writeF ("SetAttributes[ SC, Orderless ];\n");
  writeF ("\n");
  writeF ("SC[ a_ , b_ + c_ ] := SC[a,b]+SC[a,c];\n");
  writeF ("\n");
  writeF ("SC[ x_?NumberQ * a_ , b_ ] := x * SC[ a, b ]\n");
  writeF ("\n");
  writeF ("\n");

  emitconvlow (prtclNum);

  writeF ("\ninitSum;\n");
}


static void 
diagramMath (vcsect * vcs, catrec * cr)
{
  writeF ("\n(*\n");
  writeF ("  Diagram  %d in subprocess %d\n", cr->ndiagr_, cr->nsub_);
  if (vcs != NULL)
    DiagramToOutFile (vcs, 0, ' ');
  writeF ("*)\n");
  emitexpression (cr);

  writeF ("\naddToSum;\n");
}

static void 
endMath (int *prtclNum)
{
  writeF ("\nfinishSum;\n");
  outFileClose ();
}

void 
makeMathOutput (void)
{
  makeOutput (startMath, diagramMath, endMath);
}
