/*****************************************************************************
 *                                                                          
 * This software module was originally developed by 
 *
 * Martina Eckert (UPM-GTI / ACTS-MoMuSys)
 *
 * in the course of development of the MPEG-4 Video (ISO/IEC 14496-2) standard.
 * This software module is an implementation of a part of one or more MPEG-4 
 * Video (ISO/IEC 14496-2) tools as specified by the MPEG-4 Video (ISO/IEC 
 * 14496-2) standard. 
 *
 * ISO/IEC gives users of the MPEG-4 Video (ISO/IEC 14496-2) standard free 
 * license to this software module or modifications thereof for use in hardware
 * or software products claiming conformance to the MPEG-4 Video (ISO/IEC 
 * 14496-2) standard. 
 *
 * Those intending to use this software module in hardware or software products
 * are advised that its use may infringe existing patents. The original 
 * developer of this software module and his/her company, the subsequent 
 * editors and their companies, and ISO/IEC have no liability for use of this 
 * software module or modifications thereof in an implementation. Copyright is 
 * not released for non MPEG-4 Video (ISO/IEC 14496-2) Standard conforming 
 * products. 
 *
 * ACTS-MoMuSys partners retain full right to use the code for his/her own 
 * purpose, assign or donate the code to a third party and to inhibit third 
 * parties from using the code for non MPEG-4 Video (ISO/IEC 14496-2) Standard
 * conforming products. This copyright notice must be included in all copies or
 * derivative works. 
 *
 * Copyright (c) 1997
 *
 *****************************************************************************/

/***********************************************************HeaderBegin*******
 *                                                                         
 * File:        rc_upm1.c
 *
 * Author:      Martina Eckert, UPM-GTI
 *
 * Created:     18-06-97
 *                                                                         
 * Description: UPM1 control functions
 *
 * Notes:       
 *
 * Flags:       -D_RC_DEBUG_  -  RC debugging   
 *
 * Modified:
 *      14.07.97 M. Eckert: Remove limitation of VO/VOL ID numbers.
 *      11.12.97 M. Eckert: Get RC Parameters from own struct RC_CFG_PARAM
 *      15.12.97 M. Eckert: New function get_rc_cfg_upm1
 *                          Introduction of "mode" for calculation of
 *                          distortion
 *      27.01.98 M. Eckert: Modifications in RC_UPM1_QuantAdjust()
 *      03.03.98 M. Eckert: Change bitrate form UInt to Int
 *                                 
 ***********************************************************HeaderEnd*********/

/************************    INCLUDE FILES    ********************************/

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#include "rc.h"
#include "momusys.h"
#include "mom_vop.h"
#include "vm_config.h"
#include "mom_vol.h"
#include "mom_structs.h"
#include "vm_enc_defs.h"


#define MAX_DIFF 1E-3

static RC_HIST      rc_hist_upm[MAX_NUM_VOS][MAX_NUM_VOLS][3];  /* History of each VOL */
static RC_CFG_PARAM rc_cfg_upm[MAX_NUM_VOS][MAX_NUM_VOLS];   /* RC parameter */


/***********************************************************CommentBegin******
 *
 * -- min_rld --
 *
 * Author : 
 *      Martina Eckert, UPM-GTI     
 *
 * Created :            
 *      18-06-97
 *
 * Purpose :
 *      Minimization Function for lambda
 * 
 * Arguments in :       
 *     Int    *vo_list   -  To access all VOLs
 *     Double lambda_r   -  Search variable
 *     Double lambda_d   -  Search variable
 *     Int   (* rate)(RC_HIST *rch, Int vo_i, Int vol_i, Int q, Double mad, Int frame_type)  
 *                       -  Rate functions 
 *     Double (* dist)(RC_HIST *rch, Int vo_i, Int vol_i, Int q, Int mode, Int frame_type) 
 *                       -  Distortion functions 
 *     Double mad        -  MAD 
 *     Int    mode       -  0 = calculation of distortion per pixel,
 *                          1 = calculation of total distortion 
 *     Int    frame_type -  I=0, P=1, B=2
 *
 * Arguments in/out :   
 *     Int    qp[][]   -  Decisions 
 *     Double *R       -  Sum of estimated rates 
 *     Double *D       -  Sum of weighted distortions 
 *
 * Arguments out :      
 *      -
 *
 * Return values :      
 *      -
 *
 * Side effects :       
 *      -
 *
 * Description :        
 *
 *
 * See also :
 *
 *
 * Modified : 
 *       05.12.97 M.Eckert: History parameter in rate and distortion functions
 *
 ***********************************************************CommentEnd********/

static void min_rld(
                    VOConfig *vo_list,
                    Double lambda_r,
                    Double lambda_d,
                    Int   (* rate)(RC_HIST *rch,
				    Int vo_i, Int vol_i, Int q, Double mad,
				    Int frame_type), 
                    Double (* dist)(RC_HIST *rch,
				    Int vo_i, Int vol_i, 
				    Int q, Int mode,
				    Int frame_type), 
                    Double mad, 
                    Int    qp[][MAX_NUM_VOLS],     
                    Double *R,       
                    Double *D,
		    Int    mode,
		    Int    frame_type
                    )
{

   Int    vo_i, vol_i, q, min_qp, max_qp;
   Double r_iq, d_iq, c;
   Double r_min[MAX_NUM_VOS][MAX_NUM_VOLS], d_min[MAX_NUM_VOS][MAX_NUM_VOLS];
   VOConfig   *curr_vo;
   VolConfig  *curr_vol;


   *D=0;
   *R=0; 

   curr_vo = vo_list;
   while(curr_vo != NULL)
   {
      vo_i = GetVOConfigId(curr_vo);
      curr_vol =  GetVOConfigLayers(curr_vo);
      while(curr_vol != NULL)
      {
         Double c_min=1E99; 
         vol_i = GetVolConfigId(curr_vol);

         /* Search qp in full range [1..31]: */
         /* for (q = MIN_QUANT; q <= MAX_QUANT; q++)*/

         /* qp range control within the loop, search in range of last_qp+-5: */
	 /* If the last n qp's have been the same, exclude this value
	    as possibility! */

	 if (first_frame(&rc_hist_upm[vo_i][vol_i][frame_type])) 
	 {
	   min_qp = rc_upm_get_QPfirst(&rc_cfg_upm[vo_i][vol_i], frame_type);
	   max_qp = min_qp + 1;
	 }
	 else
	 {
	   min_qp = rch_min_qp(&rc_hist_upm[vo_i][vol_i][frame_type]);
	   max_qp = rch_max_qp(&rc_hist_upm[vo_i][vol_i][frame_type]);
	 }

         for (q = min_qp; q <= max_qp; q++)
         {
	   if (!first_frame(&rc_hist_upm[vo_i][vol_i][frame_type])) 
	     if (q == rch_exclude_qp(&rc_hist_upm[vo_i][vol_i][frame_type])){
#ifdef _RC_DEBUG_
	       printf("!!!! The last %d qp were equal, %d is excluded \n",
		      QP_INC, q);
#endif
	       continue;
	     }  /* A return value != 0 means to exclude this qp */

	    r_iq = (Double) (*rate)(&rc_hist_upm[vo_i][vol_i][frame_type], 
				    vo_i, vol_i, q, mad, frame_type); 
	    if (rc_get_RCParam(&rc_cfg_upm[vo_i][vol_i], frame_type) == 0.0) 
	       error_exit("RC_UPM1 - min_rld: RC Parameter 1 has to be != 0 !!!\n");  
	    d_iq = rc_get_RCParam(&rc_cfg_upm[vo_i][vol_i], frame_type) *
	       (*dist)(&rc_hist_upm[vo_i][vol_i][frame_type], 
		       vo_i, vol_i, q, mode, frame_type);
	    c = lambda_r * r_iq + lambda_d * d_iq;
	    
#ifdef _RC_DEBUG_
	    /*
              fprintf(stdout,"r[%d]=%f, d[%d]=%f, c[%d]=%f\n", 
              q, r_iq, q, d_iq, q, c);
              fflush(stdout);
	      */
#endif
            if (c < c_min)
            {
               c_min = c;
               qp[vo_i][vol_i] = q;
               
               r_min[vo_i][vol_i] = r_iq;
               d_min[vo_i][vol_i] = d_iq;
            }
         }
         curr_vol = GetVolConfigNext(curr_vol);

         *R += r_min[vo_i][vol_i];
         *D += d_min[vo_i][vol_i];

#ifdef _RC_DEBUG_
         fprintf(stdout,"Smallest: r([%d,%d],%d) = %f, d([%d,%d],%d) = %f \n",
                 vo_i, vol_i, qp[vo_i][vol_i], r_min[vo_i][vol_i], 
                 vo_i, vol_i, qp[vo_i][vol_i], d_min[vo_i][vol_i]);
         fflush(stdout);
#endif
     }
      curr_vo = GetVOConfigNext(curr_vo);
   }

}

/***********************************************************CommentBegin******
 *
 * -- MinOptimization --
 *
 * Author : 
 *      Martina Eckert, UPM-GTI     
 *
 * Created :            
 *      18-06-97
 *
 * Purpose :
 *      Calculates a distribution of the global target bitrate between the
 *      different VOs by minimization of the sum of weighted distortions.
 * 
 * Arguments in :       
 *     Int    *vo_list   -  To access all VOLs
 *     Double R          -  Global target bit rate
 *     Int   (* rate)(RC_HIST *rch, Int vo_i, Int vol_i, Int q, Double mad, Int frame_type) 
 *                       -  Rate functions 
 *     Double (* dist)(RC_HIST *rch, Int vo_i, Int vol_i, Int q, Int mode, Int frame_type) 
 *                       -  Distortion functions 
 *     Double mad        -  MAD 
 *     Int    mode       -  0 = calculation of distortion per pixel,
 *                          1 = calculation of total distortion 
 *     Int    frame_type -  I=0, P=1, B=2
 *
 * Arguments in/out :   
 *     Int    qp[][]    -  Decisions 
 *
 * Arguments out :      
 *      -
 *
 * Return values :      
 *     Double r_lambda  -  Predicted bitrate sum for all VOs
 *
 * Side effects :       
 *      -
 *
 * Description :        
 *
 *
 * See also :
 *
 *
 * Modified :           
 *       05.12.97 M.Eckert: History parameter in rate and distortion functions
 *
 *
 ***********************************************************CommentEnd********/

static Double MinOptimization(          
                              VOConfig *vo_list,
                              Double R,          
                              Int   (* rate)(RC_HIST *rch, 
					      Int vo_i, Int vol_i, 
                                              Int q, Double mad,
					      Int frame_type), 
                              Double (* dist)(RC_HIST *rch,
					      Int vo_i, Int vol_i, 
                                              Int q, Int mode,
					      Int frame_type), 
                              Double mad,       
                              Int    qp[][MAX_NUM_VOLS],
			      Int    mode,
			      Int    frame_type
                              )
{

   Double lambda1=0, lambda2;
   Double r_lambda, d_lambda, lambda_mid;

   /* Search for the upper limit of lambda */
  
#ifdef _RC_DEBUG_
   fprintf(stdout,"lambda = %f \n", lambda1);fflush(stdout);
#endif

   /* Calculate r_lambda_min */

   min_rld(vo_list, 1, 0, 
           rate, dist, 
           mad, qp, 
           &r_lambda, &d_lambda,
	   mode, frame_type);


   if (r_lambda > R)
   {
#ifdef _RC_DEBUG_
      fprintf(stdout,"--> R_lambda = %f, D = %f \n", r_lambda, d_lambda); 
      fprintf(stdout," R_lambda > R !\n");fflush(stdout);
#endif
      return r_lambda;
   }

   /* Calculate r_lambda_inf */

   min_rld(vo_list, 
           0, 1, 
           rate, dist, 
           mad, qp, 
           &r_lambda, &d_lambda,
	   mode, frame_type);

   if (r_lambda < R)
   {
#ifdef _RC_DEBUG_
      fprintf(stdout,"--> R_lambda = %f, D = %f \n", r_lambda, d_lambda); 
      fprintf(stdout," R_lambda > R !\n");fflush(stdout);
#endif
      return r_lambda;
   }
   else
   {
      lambda2 = 1;
      do
      {
#ifdef _RC_DEBUG_
         fprintf(stdout,"lambda = %f \n", lambda2);
#endif

         min_rld(vo_list, 
                 1, lambda2, 
                 rate, dist, 
                 mad, qp, 
                 &r_lambda, &d_lambda,
		 mode, frame_type);

#ifdef _RC_DEBUG_
         fprintf(stdout,"--> R_lambda = %f, D = %f \n", r_lambda, d_lambda);
         fflush(stdout);
#endif
         lambda2 *= 2;

      }
      while (r_lambda < R);
   }
  

   /* Middle point search */

#ifdef _RC_DEBUG_
   fprintf(stdout,"Middle point search \n");fflush(stdout);
#endif
  
   while ( (lambda2 - lambda1 > MAX_DIFF) || (r_lambda > R) )
   {
      lambda_mid = (lambda1 + lambda2) / 2;
      
      min_rld(vo_list, 
              1, lambda_mid, 
              rate, dist, 
              mad, qp, 
              &r_lambda, &d_lambda,
	      mode, frame_type);
         
#ifdef _RC_DEBUG_
      fprintf(stdout,"lambda = %f -> R_lambda = %f, D = %f \n", 
              lambda_mid, r_lambda, d_lambda);
      fflush(stdout);
#endif
 
      if (r_lambda < R)
         lambda1 = lambda_mid;
      else
         lambda2 = lambda_mid;
   }
   
   
   return r_lambda;
}

/***********************************************************CommentBegin******
 *
 * -- RC_UPM1_QuantAdjust --
 *
 * Author : 
 *      Martina Eckert, UPM-GTI     
 *
 * Created :            
 *      18-06-97
 *
 * Purpose :
 *      1. UPM control algorithm for global rate distribution with the 
 *      selected prediction model.
 *      Returns QP for current VO.
 * 
 * Arguments in :       
 *      Int    vo_id          -  VO Id
 *      Int    vol_id         -  VOL Id
 *      VOConfig *vo_list     -  Access to all VOLs
 *      Double R              -  Global target bitrate 
 *      Double mad            -  Current MAD
 *      UInt   num_pels       -  Current number of pixels in VO
 *      Int    rc_rate_model  -  Used rate prediction model
 *      Int    rc_dist_model  -  Used distortion prediction model
 *      Int    mode           -  0 = calculation of distortion per pixel,
 *                               1 = calculation of total distortion 
 *      Int    frame_type     -  I=0, P=1, B=2
 *
 * Arguments in/out :   
 *      -
 *
 * Arguments out :      
 *      -
 *
 * Return values :      
 *      Int    qp       - Quantization parameter for current VO
 *
 * Side effects :       
 *      -
 *
 * Description :        
 *
 *
 * See also :
 *      file "README"
 *
 * Modified : 
 *       03.12.97 M.Eckert: Changes concerning model improvement from jir
                            -D_UPM2-JIR_ includes additional printouts
 *       05.12.97 M.Eckert: History parameter in rate and distortion functions,
 *                          move set_process_flag from rc_upm_model.c to here.
 *       15.12.97 M.Eckert: Introduction of "mode" for calculation of
 *                          distortion
 *       27.01.98 M.Eckert: Modification of QP for first frame
 *
 ***********************************************************CommentEnd********/

Int RC_UPM1_QuantAdjust(
                        Int    vo_id, 
                        Int    vol_id,
                        VOConfig *vo_list,
                        Double R,         
                        Double mad,       
                        UInt   num_pels_vop,
                        Int    rc_rate_model,
                        Int    rc_dist_model,
                        Int    mode,
			Int    frame_type
                        )
                        
{
   RC_CFG_PARAM *rc_cfg = &rc_cfg_upm[vo_id][vol_id];
   Int    (* rate_model) (RC_HIST*, Int, Int, Int, Double, Int) = NULL;
   Double (* dist_model) (RC_HIST*, Int, Int, Int, Int, Int) = NULL;

   Int       qp[MAX_NUM_VOS][MAX_NUM_VOLS];   /* QPs */
   Short     vol_i, vo_i;                     /* Counter */
   Int       first_vo, first_vol;
   VOConfig  *curr_vo;
   VolConfig *curr_vol;

#ifdef _RC_DEBUG_
   Int     last_vo_id, last_vol_id;
   Double  r_tot;                   /* Totally achieved bit-rate */
#endif

#if _UPM2-JIR_
   /* JIR - model UPM2: */
   static  Int qp_inc[MAX_NUM_VOS][MAX_NUM_VOLS];
   static  Int init=0;
   static  Int count=0;
#endif

   /* Initialize process flags for global control: */

   curr_vo = vo_list;
   first_vo = GetVOConfigId(curr_vo);
   curr_vol =  GetVOConfigLayers(curr_vo);
   first_vol = GetVolConfigId(curr_vol);
   
   if (vo_id == first_vo && vol_id == first_vol)
      while(curr_vo != NULL)
      {
	 vo_i = GetVOConfigId(curr_vo);
	 curr_vol = GetVOConfigLayers(curr_vo);
	 while(curr_vol != NULL)
	 {
	    vol_i = GetVolConfigId(curr_vol);
	    /* Status of all VOs: unprocessed: */
	    rch_set_process_flag(&rc_hist_upm[vo_i][vol_i][frame_type], 2);    
	    curr_vol = GetVolConfigNext(curr_vol);
	 }
	 curr_vo = GetVOConfigNext(curr_vo);
      }

   /* Set process flag for currently processed VO */

   rch_set_process_flag(&rc_hist_upm[vo_id][vol_id][frame_type], 1);   /* VOL = [vo_id,vol_id] is 
							      currently processed */
#if _UPM2-JIR_
  /* JIR - model UPM2: */
   count++;

   if (!init)
   {
      Int i, j, inc=1;
      for (i=0; i<MAX_NUM_VOS; i++)
         for (j=0; j<MAX_NUM_VOLS; j++)
         {
            qp_inc[i][j] = inc;
            inc *= (-1);
	 }
      init = 1;
   }
#endif   

#ifdef _RC_DEBUG_
  /*** JIR ***/printf("JIR: model_target= %d\n", (int)R);
#endif

   for(vo_i = 0; vo_i < MAX_NUM_VOS; vo_i++)
      for(vol_i = 0; vol_i < MAX_NUM_VOLS; vol_i++)
      {
         qp[vo_i][vol_i] = 0;
      }

#ifdef _RC_DEBUG_

   /* Find ID of last VOL of frame: */
   curr_vo = vo_list;
   while(curr_vo != NULL)
   {
      curr_vol = GetVOConfigLayers(curr_vo);
      while(curr_vol != NULL)
      {
         vo_i = GetVOConfigId(curr_vo);
         vol_i = GetVolConfigId(curr_vol);
         curr_vol = GetVolConfigNext(curr_vol);
      }
      curr_vo = GetVOConfigNext(curr_vo);
   }

   last_vo_id = vo_i;
   last_vol_id = vol_i;

   fprintf(stdout,"Global target rate: %f \n\n", R); fflush(stdout); 
#endif

   rch_store(&rc_hist_upm[vo_id][vol_id][frame_type], (Int)num_pels_vop, mad);

   if (first_frame(&rc_hist_upm[vo_id][vol_id][frame_type])) 
     {
     /* Code  all VOs of first frame with initial qp: */
     qp[vo_id][vol_id] = rc_upm_get_QPfirst(rc_cfg, frame_type); 
#ifdef _RC_DEBUG_
      printf("first qp: %d\n",qp[vo_id][vol_id]);
#endif
     }

   else  
   {

      /* Calculate QPs of optimal global distribution of target bit rate: */
      
      switch (rc_rate_model) 
         {
         case RC_MODEL_UPM1:
         case RC_MODEL_UPM2:
            rate_model = RC_UPM_pred_bits;
            break; 
         default:
            error_exit("RC_UPM1_QuantAdjust: Error: Mode not supported\n");
         }     

      switch (rc_dist_model) 
         {
         case RC_MODEL_UPM1:
         case RC_MODEL_UPM2:
            dist_model = RC_UPM_pred_dist;
            break; 
         default:
            error_exit("RC_UPM1_QuantAdjust: Error: Mode not supported\n");
         }     


#ifdef _RC_DEBUG_
      r_tot = MinOptimization(vo_list, R,
                              rate_model, dist_model, 
                              mad, qp, mode,
			      frame_type); 
#else
      MinOptimization(vo_list, R,
		      rate_model, dist_model, 
		      mad, qp, mode,
		      frame_type); 
#endif
   }



#ifdef _RC_DEBUG_

#if _UPM2-JIR_ 
   /* JIR: Writing the model parameters */
   /* meb: small error in reasoning, if more than 1 VOs are coded,
	 if condition will be executed too early! */
  if (count > 2)
  {
     double p1r, p2r, p3r, p1d, p2d, p3d;
     RC_HIST *rch = &rc_hist_upm[vo_id][vol_id][frame_type];
   
     p3r = (double)rate_model(rch, vo_id, vol_id, 1000000, 1.);
     p1r =((double)rate_model(rch, vo_id, vol_id, 1, 1.)
	    -(double)rate_model(rch, vo_id, vol_id, -1, 1.))/2.;
     p2r = (double)rate_model(rch, vo_id, vol_id, 1, 1.)-p1r-p3r;
     p3d =  dist_model(rch, vo_id, vol_id, 0, mode, frame_type);
     p1d = (dist_model(rch, vo_id, vol_id, 1, mode, frame_type)
	    -dist_model(rch, vo_id, vol_id, -1, mode, frame_type))/2.;
     p2d =  dist_model(rch, vo_id, vol_id, 1, mode, frame_type)-p1d-p3d;
     
     printf("JIR: QP: p1r= %f;  p2r= %f;  p3r= %f; p1d= %f; p2d= %f p3d= %f;\n",
            p1r, p2r, p3r, p1d, p2d, p3d);
     printf("JIR: QP: old_qp= %d  new_qp= %d  inc_qp= %d\n",
	    rch_get_last_qp(&rc_hist_upm[vo_id][vol_id][frame_type]), qp[vo_id][vol_id], qp_inc[vo_id][vol_id]);
  }

#endif
#endif

  /* Suppress great deviation of qp if search range [1..31]:
  
  qp[vo_id][vol_id] = rch_qp_range_control(&rc_hist_upm[vo_id][vol_id][frame_type], qp[vo_id][vol_id]);

  */

#ifdef _RC_DEBUG_

  if (vo_id == last_vo_id && vol_id == last_vol_id)

     WRITE_INT("rate_script",r_tot);

#endif

#if _UPM2-JIR_

  /* JIR: Avoid unchanged QP */

  if (count > 2)
#ifdef _RC_DEBUG_
     printf("JIR: QP: old= %d  new= %d  inc= %d\n", rch_get_last_qp(&rc_hist_upm[vo_id][vol_id][frame_type]), qp[vo_id][vol_id], qp_inc[vo_id][vol_id]);
#endif

  if (count > 2 && rch_get_last_qp(&rc_hist_upm[vo_id][vol_id][frame_type]) == qp[vo_id][vol_id])
  {
     if (qp[vo_id][vol_id] == MAX_QUANT)
        qp[vo_id][vol_id] = MAX_QUANT-1;
     else if (qp[vo_id][vol_id] == MIN_QUANT)
        qp[vo_id][vol_id] = MIN_QUANT+1;
     else
     {
        qp[vo_id][vol_id] += qp_inc[vo_id][vol_id];
        qp_inc[vo_id][vol_id] *= (-1);
     }
  }
#endif

  /* Store results of current VO in history: */

  rch_store_qp_before(&rc_hist_upm[vo_id][vol_id][frame_type], qp[vo_id][vol_id]);

#ifdef _RC_DEBUG_
/*** JIR ***/printf("JIR: qp= %d\n", qp[vo_id][vol_id]);
#endif

  rch_set_process_flag(&rc_hist_upm[vo_id][vol_id][frame_type], 0);   /*  VOL = [vo_id,vol_id] has 
							      been finished */
  return qp[vo_id][vol_id];
}

/***********************************************************CommentBegin******
 *
 * -- get_rch_upm1 --
 *
 * Author : 
 *      Martina Eckert, UPM-GTI     
 *
 * Created :            
 *      05.12.97
 *
 * Purpose :
 *      Access to history data from other files
 *
 * Arguments in :       
 *      Int    vo_id   -  VO Id
 *      Int    vol_id  -  VOL Id
 *
 * Arguments in/out :   
 *      -
 *
 * Arguments out :      
 *      -
 *
 * Return values :      
 *      RC_HIST  *rch  - History data array  
 *
 *
 * Modified : 
 *
 *
 ***********************************************************CommentEnd********/

RC_HIST *get_rch_upm1(
		      Int  vo_id,
		      Int  vol_id,
		      Int  frame_type
		      )
{

return &rc_hist_upm[vo_id][vol_id][frame_type];

}

/***********************************************************CommentBegin******
 *
 * -- get_rc_cfg_upm1 --
 *
 * Author : 
 *      Martina Eckert, UPM-GTI     
 *
 * Created :            
 *      15.12.97
 *
 * Purpose :
 *      Access to history data from other files
 *
 * Arguments in :       
 *      Int    vo_id   -  VO Id
 *      Int    vol_id  -  VOL Id
 *
 * Arguments in/out :   
 *      -
 *
 * Arguments out :      
 *      -
 *
 * Return values :      
 *      RC_CFG_PARAM  *rc_cfg  - Configuration data (model parameters)
 *
 *
 * Modified : 
 *
 *
 ***********************************************************CommentEnd********/

RC_CFG_PARAM *get_rc_cfg_upm1(
			      Int  vo_id,
			      Int  vol_id
			      )
{

   return &rc_cfg_upm[vo_id][vol_id];

}

/*********************************************************** End of file ***/
