/*****

*Property of the University of British Columbia (UBC),

*Copyright 2001, by UBC.

*

*By receiving this code, you are agreeing to the following terms:

*1. You will use this code for academic purposes only.

*2. For academic use only, you may distribute the binary or executable code

*   to persons at UBC or the Univ. of Western Australia who have previously 

*   read and agreed to these terms, but you must distribute the SOURCE code

*   with it. 

*3. Each file of source code so distributed must have this header attached.

*4. If the code is revised, the programmer's name and revision date must be added

*   to the Revision List below, as well as the revisions identified in the code.

*5. You will not make this code more widely available via any method such as 

*   publishing in print, email mail-list, usenet posting, website etc.

*6. UBC reserves all rights to this work and all derivative works.

*

*For other proposed purposes please contact:

*The University-Industry Liaison Office 

*IRC Room 331 - 2194 Health Sciences Mall 

*University of British Columbia 

*Vancouver, BC, Canada V6T 1Z3 

*Tel: (604) 822-8580 

*Fax: (604) 822-8589 

*

*or contact: 

*Peter D. Lawrence, Professor at peterl@ece.ubc.ca or 

*Greg Z. Grudic, Assistant Professor, at grudic@cs.colorado.edu

*

*Revision List: 

*Greg Grudic, August 28, 1998.

*****/



/*

%

% File:		pc.c

% Program: 	Functions for loading and evaluating a Poly_Cascade

%

% Author:	Greg Grudic

%

*/



#include "pc.h"



#include <stdio.h>





#undef COUNT_PARAMETERS





My_Real Evaluate_Poly_Cascade(Cascade_Poly *pc,

			      My_Real *x_in)

{

  int i, k;

  My_Real t1, out, x[POLY_DIM];

  Poly *cp;



  My_Real Eval_Poly(Poly *poly, My_Real x[POLY_DIM]);







  for ( i = 0; i < (int)pc->dim; i++ )

    {

      t1 = Scale(x_in[i], pc->m_scale[i], pc->b_scale[i]);

      pc->x_s[i] = t1;

    }



  out = pc->ave_value;



  cp = pc->first_poly;

  x[0] = pc->x_s[pc->first_input];

  for ( k = 1; k < POLY_DIM; k++ )

    x[k] = pc->x_s[cp->input_num[k-1]];



  t1 = Eval_Poly(cp,x);

  x[0] = Scale(t1,cp->m_scale_out,cp->b_scale_out);

  out = out + (cp->scale_to_output * x[0]);

  cp = cp->np;

  for ( i = 1; i < (int)pc->num_of_levels; i++)

    {

      for ( k = 1; k < POLY_DIM; k++ )

	x[k] = pc->x_s[cp->input_num[k-1]];



      t1 = Eval_Poly(cp,x);

      x[0] = Scale(t1,cp->m_scale_out,cp->b_scale_out);

      out = out + (cp->scale_to_output * x[0]);

      cp = cp->np;

    }



  return(out);

}



void Load_Poly_Cascade(Cascade_Poly *pc, FILE *fp)

{

  int i, i_tmp1, i_tmp2;

  Poly *cp;



#ifdef COUNT_PARAMETERS

  int num_of_par;

  num_of_par = 0;

#endif



  fread(&(i_tmp1),sizeof(int),1,fp);

  fread(&(i_tmp2),sizeof(int),1,fp);

  if ( (i_tmp1 != POLY_DIM)  ||  (i_tmp2 != POLY_TERMS) )

    {

      printf("Program compiled for: POLY_DIM = %d, POLY_TERMS = %d\n",

	     POLY_DIM, POLY_TERMS);

      printf("pc.s requires: POLY_DIM = %d, POLY_TERMS = %d\n",

	     i_tmp1, i_tmp2);

      exit(-1);

    }



  fread(&(pc->dim),sizeof(unsigned int),1,fp);

  fread(&(pc->first_input),sizeof(unsigned int),1,fp);

  fread(&(pc->num_of_levels),sizeof(unsigned int),1,fp);



  fread(&(pc->ave_value),sizeof(My_Real),1,fp);



  pc->x_s = (My_Real *)

    malloc((unsigned)pc->dim * (sizeof(My_Real)));

  if (!(pc->x_s))

    {

      printf("Cannot allocate pc->x_s!!\n");

    }



  pc->m_scale = (My_Real *)

    malloc((unsigned)pc->dim * (sizeof(My_Real)));

  if (!(pc->m_scale))

    {

      printf("Cannot allocate pc->m_scale!!\n");

    }

  

  pc->b_scale = (My_Real *)

    malloc((unsigned)pc->dim * (sizeof(My_Real)));

  if (!(pc->b_scale))

    {

      printf("Cannot allocate b_pc->pc->b_scale!!\n");

    } 



  fread((pc->m_scale),sizeof(My_Real),pc->dim,fp);

  fread((pc->b_scale),sizeof(My_Real),pc->dim,fp);



  pc->first_poly = (Poly *)

    malloc((unsigned)(sizeof(Poly)));

  if (!(pc->first_poly))

    {

      printf("Cannot allocate pc->first_poly!!\n");

    }



  cp = pc->first_poly;

  cp->np = NULL;

  for ( i = 0; i < (int)pc->num_of_levels; i++ )

    {

      fread((cp->input_num),sizeof(unsigned int),LEVEL_INPUTS,fp);

      fread((cp->a),sizeof(My_Real),POLY_TERMS,fp);



#ifdef COUNT_PARAMETERS

      num_of_par = num_of_par + POLY_TERMS;

#endif

      fread(&(cp->scale_to_output),sizeof(My_Real),1,fp);   

      fread(&(cp->m_scale_out),sizeof(My_Real),1,fp);   

      fread(&(cp->b_scale_out),sizeof(My_Real),1,fp);



      if ( i < (int)pc->num_of_levels - 1 )

	{

	  cp->np = (Poly *)

	    malloc((unsigned)(sizeof(Poly)));

	  if (!(cp->np))

	    {

	      printf("Cannot allocate cp->np!!\n");

	    }

	  

	  cp = cp->np;

	  cp->np = NULL;

	}

    }



#ifdef COUNT_PARAMETERS

  printf("================================\n");

  printf(" num_of_par = %d\n",num_of_par);

  printf("================================\n");

  fflush(stdout);

#endif



}



My_Real Eval_Poly(Poly *poly, 

		  My_Real x[POLY_DIM])

{

  My_Real tot;

  My_Real term[NON_1_INPUTS];

  int i;



  void Poly_Terms(My_Real *term, My_Real x[POLY_DIM]);



  Poly_Terms(term,x);



  tot = poly->a[0];



  for ( i = 0; i < NON_1_INPUTS; i++ )

    tot = tot + poly->a[i+1] * term[i];



  return(tot);

}





void Poly_Terms(My_Real *term, My_Real x[POLY_DIM])

{

  My_Real t2, t3, x1, x2;



  x1 = x[0];

  x2 = x[1];

  t2 = x1*x1;

  t3 = x2*x2;

  term[0] = x1;

  term[1] = x2;

  term[2] = x1*x2;

  term[3] = t2;

  term[4] = t3;

  term[5] = t2*x2;

  term[6] = x1*t3;

  term[7] = t2*x1;

  term[8] = t3*x2;

}



