/* 
   * Copyright (C) 1997, Alexander Pukhov 
   * Copyright (C) 2001-2003, CompHEP Collaboration
   *------------------------------------------------------
   * $Id: pvars.c,v 1.4 2003/06/25 18:46:41 kryukov Exp $
   *
   * $Log: pvars.c,v $
   * Revision 1.4  2003/06/25 18:46:41  kryukov
   * *** empty log message ***
   *
   * Revision 1.3  2003/04/22 09:01:20  kryukov
   * Apply indent to improve readability of files
   *
   * Revision 1.2  2003/04/20 17:55:02  kryukov
   * Clean up warnings during make
   *
 */
#include <limits.h>
#include <stdio.h>
#include "service2/include/tptcmac.h"
#include "polynom/include/polynom.h"

#include "physics.h"
#include "sos.h"
#include "syst2.h"
#include "pvars.h"

#ifdef STRACE
#include "test_wrt.h"
#endif
polyvars *vardef;


void 
increaseVars (polyvars * v)
{
  int oldsize = ALIG (v->nvar);
  if (++v->nvar > oldsize)
    v->vars = re_alloc (v->vars, ALIG (v->nvar) * sizeof (*v->vars));
}

void 
clearVars (polyvars * v)
{
  if (v->vars)
    {
      free (v->vars);
      v->vars = NULL;
    }
  v->nvar = 0;
}

void 
unite_vardef (polyvars * vardef_s, polyvars * vardef)
{
  int n, nn;
  char s[STRSIZ];

  for (nn = 0; nn < vardef->nvar; nn++)
    {
      strcpy (s, vardef->vars[nn].name);

      n = 0;
      while (n < vardef_s->nvar &&
	     strcmp (vardef->vars[nn].name, vardef_s->vars[n].name))
	n++;
      if (n < vardef_s->nvar)
	vardef_s->vars[n].maxdeg =
	  MAX (vardef_s->vars[n].maxdeg, vardef->vars[nn].maxdeg);
      else
	{
	  increaseVars (vardef_s);
	  strcpy (vardef_s->vars[n].name, s);
	  vardef_s->vars[n].maxdeg = vardef->vars[nn].maxdeg;
	}
    }
}


void 
addvar (char *varname, int deg)
{
  int n;

  n = 0;
  while (n < vardef->nvar && strcmp (varname, vardef->vars[n].name))
    n++;
  if (n < vardef->nvar)
    vardef->vars[n].maxdeg += deg;
  else
    {
      increaseVars (vardef);
      strcpy (vardef->vars[n].name, varname);
      vardef->vars[n].maxdeg = deg + 1;
    }
}


int 
scalarProductPos (int p1, int p2)
{
  if (p1 > p2)
    {
      int pp = p1;
      p1 = p2;
      p2 = pp;
    }
  return nmodelvar + 1 + p1 + ((p2 - 1) * (p2 - 2)) / 2;
}



int 
modelVarPos (char *s)
{
  int bt;
  for (bt = 0; bt <= nmodelvar; bt++)
    {
      if (strcmp (modelvars[bt].varname, s) == 0)
	return bt;
    }
  save_sos (14);
  fprintf (stderr, "***** modelVarPos: Reach the end. No return int val.!?\n");
  return 0;
}


void 
closevars (void)
{
  int i;
  unsigned long z;
  int wp, p1, p2;


  for (i = 0; i < vardef->nvar; i++)	/*  numeration  */
    if (cpos ('.', vardef->vars[i].name) != 0)
      {
	p1 = vardef->vars[i].name[1] - '0';
	p2 = vardef->vars[i].name[4] - '0';
	vardef->vars[i].num = scalarProductPos (p1, p2);
      }
    else
      vardef->vars[i].num = modelVarPos (vardef->vars[i].name);

  for (i = 0; i < vardef->nvar; i++)
    if (!strcmp (vardef->vars[i].name, "i"))
      {
	vardef->nvar--;
	break;
      }
  for (; i < vardef->nvar; i++)
    vardef->vars[i] = vardef->vars[i + 1];


  if (vardef->nvar > 1)		/*  Sorting  */
    {
      i = 1;
      while (i < vardef->nvar)
	if (vardef->vars[i - 1].num > vardef->vars[i].num)
	  i++;
	else
	  {
	    varinfo tmpv = vardef->vars[i - 1];
	    vardef->vars[i - 1] = vardef->vars[i];
	    vardef->vars[i] = tmpv;
	    if (i == 1)
	      ++(i);
	    else
	      --(i);
	  }
    }

  monomLength = 1;
  z = 1;
  for (i = 1; i <= vardef->nvar; i++)
    {
      if (z >= (ULONG_MAX / vardef->vars[i - 1].maxdeg))
	{
	  monomLength++;
	  z = vardef->vars[i - 1].maxdeg;
	}
      else
	z *= vardef->vars[i - 1].maxdeg;

      vardef->vars[i - 1].wordpos = monomLength;
    }

  z = 1;
  wp = monomLength;
  for (i = vardef->nvar; i >= 1; i--)
    {
      if (vardef->vars[i - 1].wordpos == wp)
	{
	  vardef->vars[i - 1].zerodeg = z;
	  z *= vardef->vars[i - 1].maxdeg;
	}
      else
	{
	  vardef->vars[i - 1].zerodeg = 1;
	  z = vardef->vars[i - 1].maxdeg;
	  --(wp);
	}
    }
  garbage = NULL;
#ifdef STRACE
  tracePrn ("vars position \n");
  for (i = 0; i < vardef->nvar; i++)
    {
      tracePrn (" name= %s pos= %d maxdeg=  %lu zerodeg= %lu\n",
      vardef->vars[i].name, vardef->vars[i].wordpos, vardef->vars[i].maxdeg,
		vardef->vars[i].zerodeg);
    }
  tracePrn ("monomLength=  %d\n", monomLength);
#endif

}
