text:
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
#include <math.h>
#include <string.h>
#include "cconfigspace_internal.h"
#include "distribution_internal.h"

struct _ccs_distribution_mixture_data_s {
	_ccs_distribution_common_data_t  common_data;
	size_t                           num_distributions;
	ccs_distribution_t              *distributions;
	ccs_interval_t                  *bounds;
        ccs_float_t                     *weights;
};
typedef struct _ccs_distribution_mixture_data_s _ccs_distribution_mixture_data_t;

static ccs_result_t
_ccs_distribution_mixture_del(ccs_object_t o) {
	struct _ccs_distribution_mixture_data_s *data =
		(struct _ccs_distribution_mixture_data_s *)(((ccs_distribution_t)o)->data);
	for (size_t i = 0; i < data->num_distributions; i++) {
		ccs_release_object(data->distributions[i]);
	}
	return CCS_SUCCESS;
}

static ccs_result_t
_ccs_distribution_mixture_get_bounds(_ccs_distribution_data_t *data,
                                     ccs_interval_t           *interval_ret);

static ccs_result_t
_ccs_distribution_mixture_samples(_ccs_distribution_data_t *data,
                                  ccs_rng_t                 rng,
                                  size_t                    num_values,
                                  ccs_numeric_t            *values);

static ccs_result_t
_ccs_distribution_mixture_strided_samples(_ccs_distribution_data_t *data,
                                          ccs_rng_t                 rng,
                                          size_t                    num_values,
                                          size_t                    stride,
                                          ccs_numeric_t            *values);

static ccs_result_t
_ccs_distribution_mixture_soa_samples(_ccs_distribution_data_t  *data,
                                      ccs_rng_t                  rng,
                                      size_t                     num_values,
                                      ccs_numeric_t            **values);

static _ccs_distribution_ops_t _ccs_distribution_mixture_ops = {
	{ &_ccs_distribution_mixture_del },
	&_ccs_distribution_mixture_samples,
	&_ccs_distribution_mixture_get_bounds,
	&_ccs_distribution_mixture_strided_samples,
	&_ccs_distribution_mixture_soa_samples
};

ccs_result_t
ccs_create_mixture_distribution(size_t              num_distributions,
                                ccs_distribution_t *distributions,
                                ccs_float_t        *weights,
                                ccs_distribution_t *distribution_ret) {
	CCS_CHECK_ARY(num_distributions, distributions);
	CCS_CHECK_ARY(num_distributions, weights);
	CCS_CHECK_PTR(distribution_ret);
	if (!num_distributions || num_distributions > INT64_MAX)
		return -CCS_INVALID_VALUE;
	ccs_float_t sum = 0.0;

	size_t             dimension, i, j;
	ccs_result_t       err;
	CCS_VALIDATE(ccs_distribution_get_dimension(distributions[0], &dimension));
	for(i = 1; i < num_distributions; i++) {
		size_t             dimension_tmp;
		CCS_VALIDATE(ccs_distribution_get_dimension(distributions[i], &dimension_tmp));
		if (dimension != dimension_tmp)
			return -CCS_INVALID_DISTRIBUTION;
	}

	for(i = 0; i < num_distributions; i++) {
		if (weights[i] < 0.0)
			return -CCS_INVALID_VALUE;
		sum += weights[i];
	}
	if (sum == 0.0)
		return -CCS_INVALID_VALUE;
	ccs_float_t inv_sum = 1.0/sum;
	if (isnan(inv_sum) || !isfinite(inv_sum))
		return -CCS_INVALID_VALUE;

	uintptr_t mem;
	uintptr_t cur_mem;
	uintptr_t tmp_mem;
	ccs_interval_t     *bounds_tmp;
	ccs_numeric_type_t *data_types_tmp;
	ccs_distribution_t distrib;
	_ccs_distribution_mixture_data_t *distrib_data;
	mem = (uintptr_t)calloc(1,
		sizeof(struct _ccs_distribution_s) +
		sizeof(_ccs_distribution_mixture_data_t) +
		sizeof(ccs_distribution_t)*num_distributions +
		sizeof(ccs_interval_t)*dimension +
		sizeof(ccs_float_t)*(num_distributions + 1) +
		sizeof(ccs_numeric_type_t)*dimension);

	if (!mem)
		return -CCS_OUT_OF_MEMORY;
        cur_mem = mem;

	tmp_mem = (uintptr_t)calloc(1,
		sizeof(ccs_interval_t)*num_distributions +
		sizeof(ccs_numeric_type_t)*dimension);
	if (!tmp_mem) {
		err = -CCS_OUT_OF_MEMORY;
		goto memory;
	}
	bounds_tmp = (ccs_interval_t *)tmp_mem;
	data_types_tmp = (ccs_numeric_type_t *)(tmp_mem + sizeof(ccs_interval_t)*num_distributions);

	distrib = (ccs_distribution_t)cur_mem;
	cur_mem += sizeof(struct _ccs_distribution_s);
	_ccs_object_init(&(distrib->obj), CCS_DISTRIBUTION, (_ccs_object_ops_t *)&_ccs_distribution_mixture_ops);
	distrib_data = (_ccs_distribution_mixture_data_t *)(cur_mem);
	cur_mem += sizeof(_ccs_distribution_mixture_data_t);
	distrib_data->common_data.type        = CCS_MIXTURE;
	distrib_data->common_data.dimension   = dimension;
	distrib_data->num_distributions       = num_distributions;
	distrib_data->distributions           = (ccs_distribution_t *)(cur_mem);
	cur_mem += sizeof(ccs_distribution_t)*num_distributions;
	distrib_data->bounds                  = (ccs_interval_t *)(cur_mem);
	cur_mem += sizeof(ccs_interval_t)*dimension;
	distrib_data->weights                 = (ccs_float_t *)(cur_mem);
	cur_mem += sizeof(ccs_float_t)*(num_distributions + 1);
	distrib_data->common_data.data_types  = (ccs_numeric_type_t *)(cur_mem);
	cur_mem += sizeof(ccs_numeric_type_t)*dimension;

	CCS_VALIDATE_ERR_GOTO(err,
	  ccs_distribution_get_data_types(distributions[0], distrib_data->common_data.data_types),
	  tmpmemory);
	for (i = 1; i < num_distributions; i++) {
		CCS_VALIDATE_ERR_GOTO(err,
		  ccs_distribution_get_data_types(distributions[i], data_types_tmp),
		  tmpmemory);
		for (j = 0; j < dimension; j++)
			if(distrib_data->common_data.data_types[j] != data_types_tmp[j]) {
				err = -CCS_INVALID_DISTRIBUTION;
				goto tmpmemory;
			}
	}

	CCS_VALIDATE_ERR_GOTO(err,
	  ccs_distribution_get_bounds(distributions[0], distrib_data->bounds),
	  tmpmemory);
	for (i = 1; i < num_distributions; i++) {
		CCS_VALIDATE_ERR_GOTO(err,
		  ccs_distribution_get_bounds(distributions[i], bounds_tmp),
		  tmpmemory);
		for (j = 0; j < dimension; j++) {
			CCS_VALIDATE_ERR_GOTO(err,
			  ccs_interval_union(distrib_data->bounds + j, bounds_tmp + j,
			                         distrib_data->bounds + j), tmpmemory);
		}
	}

	distrib_data->weights[0] = 0.0;
	for (i = 1; i <= num_distributions; i++) {
		distrib_data->weights[i] = distrib_data->weights[i-1] + weights[i-1] * inv_sum;
	}
	distrib_data->weights[num_distributions] = 1.0;
	if (1.0 < distrib_data->weights[num_distributions-1]) {
		free((void *)mem);
		return -CCS_INVALID_VALUE;
	}
	for (i = 0; i < num_distributions; i++) {
		CCS_VALIDATE_ERR_GOTO(err, ccs_retain_object(distributions[i]), distrib);
		distrib_data->distributions[i] = distributions[i];
	}
	distrib->data = (_ccs_distribution_data_t *)distrib_data;
	*distribution_ret = distrib;
	free((void *)tmp_mem);
	return CCS_SUCCESS;
distrib:
	for (i = 0; i < num_distributions; i++) {
		if (distrib_data->distributions[i])
			ccs_release_object(distributions[i]);
	}
tmpmemory:
	free((void *)tmp_mem);
memory:
	free((void *)mem);
	return err;
}

static ccs_result_t
_ccs_distribution_mixture_get_bounds(_ccs_distribution_data_t *data,
                                     ccs_interval_t           *interval_ret) {
	_ccs_distribution_mixture_data_t *d = (_ccs_distribution_mixture_data_t *)data;
	memcpy(interval_ret, d->bounds, d->common_data.dimension*sizeof(ccs_interval_t));
	return CCS_SUCCESS;
}

static inline _ccs_distribution_ops_t *
ccs_distribution_get_ops(ccs_distribution_t distribution) {
	return (_ccs_distribution_ops_t *)distribution->obj.ops;
}

static ccs_result_t
_ccs_distribution_mixture_samples(_ccs_distribution_data_t *data,
                                  ccs_rng_t                 rng,
                                  size_t                    num_values,
                                  ccs_numeric_t            *values) {
	_ccs_distribution_mixture_data_t *d = (_ccs_distribution_mixture_data_t *)data;
	size_t dim = d->common_data.dimension;

	gsl_rng *grng;
	CCS_VALIDATE(ccs_rng_get_gsl_rng(rng, &grng));

	for (size_t i = 0; i < num_values; i++) {
		ccs_float_t rnd = gsl_rng_uniform(grng);
		ccs_int_t index = ccs_dichotomic_search(d->num_distributions, d->weights, rnd);
		CCS_VALIDATE(ccs_distribution_get_ops(d->distributions[index])->samples(d->distributions[index]->data, rng, 1, values + i*dim));
	}
	return CCS_SUCCESS;
}

static ccs_result_t
_ccs_distribution_mixture_strided_samples(_ccs_distribution_data_t *data,
                                          ccs_rng_t                 rng,
                                          size_t                    num_values,
                                          size_t                    stride,
                                          ccs_numeric_t            *values) {
	_ccs_distribution_mixture_data_t *d = (_ccs_distribution_mixture_data_t *)data;

	gsl_rng *grng;
	CCS_VALIDATE(ccs_rng_get_gsl_rng(rng, &grng));

	for (size_t i = 0; i < num_values; i++) {
		ccs_float_t rnd = gsl_rng_uniform(grng);
		ccs_int_t index = ccs_dichotomic_search(d->num_distributions, d->weights, rnd);
		CCS_VALIDATE(ccs_distribution_get_ops(d->distributions[index])->samples(d->distributions[index]->data, rng, 1, values + i*stride));
	}
	return CCS_SUCCESS;
}

static ccs_result_t
_ccs_distribution_mixture_soa_samples(_ccs_distribution_data_t  *data,
                                      ccs_rng_t                  rng,
                                      size_t                     num_values,
                                      ccs_numeric_t            **values) {
	_ccs_distribution_mixture_data_t *d = (_ccs_distribution_mixture_data_t *)data;
	size_t dim = d->common_data.dimension;
	int needed = 0;

	ccs_numeric_t **p_values = (ccs_numeric_t**)alloca(dim*sizeof(ccs_numeric_t*));
	for (size_t i = 0; i < dim; i++)
		if (values[i]) {
			needed = 1;
			break;
		}
	if (!needed)
		return CCS_SUCCESS;

	gsl_rng *grng;
	CCS_VALIDATE(ccs_rng_get_gsl_rng(rng, &grng));

	for (size_t i = 0; i < num_values; i++) {
		ccs_float_t rnd = gsl_rng_uniform(grng);
		ccs_int_t index = ccs_dichotomic_search(d->num_distributions, d->weights, rnd);
		for (size_t j = 0; j < dim; j++)
			if (values[j])
				p_values[j] = values[j] + i;
		CCS_VALIDATE(ccs_distribution_get_ops(d->distributions[index])->soa_samples(d->distributions[index]->data, rng, 1, p_values));
	}
	return CCS_SUCCESS;
}

ccs_result_t
ccs_mixture_distribution_get_num_distributions(ccs_distribution_t  distribution,
                                               size_t             *num_distributions_ret) {
	CCS_CHECK_DISTRIBUTION(distribution, CCS_MIXTURE);
	CCS_CHECK_PTR(num_distributions_ret);
	_ccs_distribution_mixture_data_t * data = (_ccs_distribution_mixture_data_t *)distribution->data;
	*num_distributions_ret = data->num_distributions;
	return CCS_SUCCESS;
}

ccs_result_t
ccs_mixture_distribution_get_distributions(ccs_distribution_t  distribution,
                                           size_t              num_distributions,
                                           ccs_distribution_t *distributions,
                                           size_t             *num_distributions_ret) {
	CCS_CHECK_DISTRIBUTION(distribution, CCS_MIXTURE);
	CCS_CHECK_ARY(num_distributions, distributions);
	if (!distributions && !num_distributions_ret)
		return -CCS_INVALID_VALUE;
	_ccs_distribution_mixture_data_t * data = (_ccs_distribution_mixture_data_t *)distribution->data;
	if (distributions) {
		if (num_distributions < data->num_distributions)
			return -CCS_INVALID_VALUE;
		for (size_t i = 0; i < data->num_distributions; i++)
			distributions[i] = data->distributions[i];
		for (size_t i = data->num_distributions; i < num_distributions; i++)
			distributions[i] = NULL;
	}
	if (num_distributions_ret)
		*num_distributions_ret = data->num_distributions;
	return CCS_SUCCESS;
}

ccs_result_t
ccs_mixture_distribution_get_weights(ccs_distribution_t  distribution,
                                     size_t              num_weights,
                                     ccs_float_t        *weights,
                                     size_t             *num_weights_ret) {
	CCS_CHECK_DISTRIBUTION(distribution, CCS_MIXTURE);
	CCS_CHECK_ARY(num_weights, weights);
	if (!weights && !num_weights_ret)
		return -CCS_INVALID_VALUE;
	_ccs_distribution_mixture_data_t * data = (_ccs_distribution_mixture_data_t *)distribution->data;
	if (weights) {
		if (num_weights < data->num_distributions)
			return -CCS_INVALID_VALUE;
		for (size_t i = 0; i < data->num_distributions; i++)
			weights[i] = data->weights[i+1] - data->weights[i];
		for (size_t i = data->num_distributions; i < num_weights; i++)
			weights[i] = 0.0;
	}
	if (num_weights_ret)
		*num_weights_ret = data->num_distributions;
	return CCS_SUCCESS;
}

max_stars_repo_name: deephyper/CCS

max_issues_repo_name: deephyper/CCS

max_forks_repo_name: deephyper/CCS


text:
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

/*! \file oaisim.c
 * \brief oaisim top level
 * \author Navid Nikaein
 * \date 2013-2015
 * \version 1.0
 * \company Eurecom
 * \email: openair_tech@eurecom.fr
 * \note
 * \warning
 */

#include <string.h>
#include <math.h>
#include <unistd.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <cblas.h>
#include <execinfo.h>

#include "event_handler.h"
#include "SIMULATION/RF/defs.h"
#include "PHY/types.h"
#include "PHY/defs.h"
#include "PHY/LTE_TRANSPORT/proto.h"
#include "PHY/vars.h"

#include "SIMULATION/ETH_TRANSPORT/proto.h"

//#ifdef OPENAIR2
#include "LAYER2/MAC/defs.h"
#include "LAYER2/MAC/proto.h"
#include "LAYER2/MAC/vars.h"
#include "pdcp.h"
#include "RRC/LITE/vars.h"
#include "RRC/NAS/nas_config.h"

#include "SCHED/defs.h"
#include "SCHED/vars.h"
#include "system.h"

#include "PHY/TOOLS/lte_phy_scope.h"

#ifdef SMBV
// Rohde&Schwarz SMBV100A vector signal generator
#include "PHY/TOOLS/smbv.h"
char smbv_fname[] = "smbv_config_file.smbv";
unsigned short smbv_nframes = 4; // how many frames to configure 1,..,4
unsigned short config_frames[4] = {2,9,11,13};
unsigned char smbv_frame_cnt = 0;
uint8_t config_smbv = 0;
char smbv_ip[16];
#endif

#include "flexran_agent.h"

#include "oaisim_functions.h"

#include "oaisim.h"
#include "oaisim_config.h"
#include "UTIL/OCG/OCG_extern.h"
#include "cor_SF_sim.h"
#include "UTIL/OMG/omg_constants.h"
#include "UTIL/FIFO/pad_list.h"
#include "enb_app.h"

#include "../PROC/interface.h"
#include "../PROC/channel_sim_proc.h"
#include "../PROC/Tsync.h"
#include "../PROC/Process.h"

#include "UTIL/LOG/vcd_signal_dumper.h"
#include "UTIL/OTG/otg_kpi.h"
#include "assertions.h"

#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
# include "create_tasks.h"
#endif

#include "T.h"

/*
  DCI0_5MHz_TDD0_t          UL_alloc_pdu;
  DCI1A_5MHz_TDD_1_6_t      CCCH_alloc_pdu;
  DCI2_5MHz_2A_L10PRB_TDD_t DLSCH_alloc_pdu1;
  DCI2_5MHz_2A_M10PRB_TDD_t DLSCH_alloc_pdu2;
*/

#define UL_RB_ALLOC            computeRIV(lte_frame_parms->N_RB_UL,0,24)
#define CCCH_RB_ALLOC          computeRIV(lte_frame_parms->N_RB_UL,0,3)
#define RA_RB_ALLOC            computeRIV(lte_frame_parms->N_RB_UL,0,3)
#define DLSCH_RB_ALLOC         0x1fff

#define DECOR_DIST             100
#define SF_VAR                 10

//constant for OAISIM soft realtime calibration
//#define SF_DEVIATION_OFFSET_NS 100000        /*= 0.1ms : should be as a number of UE */
//#define SLEEP_STEP_US          100           /*  = 0.01ms could be adaptive, should be as a number of UE */
//#define K                      2             /* averaging coefficient */
//#define TARGET_SF_TIME_NS      1000000       /* 1ms = 1000000 ns */

uint8_t usim_test = 0;

frame_t frame = 0;
char stats_buffer[16384];
channel_desc_t *RU2UE[NUMBER_OF_RU_MAX][NUMBER_OF_UE_MAX][MAX_NUM_CCs];
channel_desc_t *UE2RU[NUMBER_OF_UE_MAX][NUMBER_OF_RU_MAX][MAX_NUM_CCs];
//Added for PHY abstraction
node_desc_t *enb_data[NUMBER_OF_RU_MAX];
node_desc_t *ue_data[NUMBER_OF_UE_MAX];

pthread_cond_t sync_cond;
pthread_mutex_t sync_mutex;
int sync_var=-1;

pthread_mutex_t subframe_mutex;
int subframe_ru_mask=0,subframe_UE_mask=0;

openair0_config_t openair0_cfg[MAX_CARDS];
uint32_t          downlink_frequency[MAX_NUM_CCs][4];
int32_t           uplink_frequency_offset[MAX_NUM_CCs][4];
openair0_rf_map rf_map[MAX_NUM_CCs];

#if defined(ENABLE_ITTI)
volatile int             start_eNB = 0;
volatile int             start_UE = 0;
#endif
volatile int                    oai_exit = 0;

//int32_t **rxdata;
//int32_t **txdata;

uint16_t sf_ahead=4;
uint8_t nfapi_mode = 0;

// Added for PHY abstraction
extern node_list* ue_node_list;
extern node_list* enb_node_list;
extern int pdcp_period, omg_period;

extern double **s_re, **s_im, **r_re, **r_im, **r_re0, **r_im0;
int map1, map2;
extern double **ShaF;
double snr_dB, sinr_dB, snr_direction; //,sinr_direction;
extern double snr_step;
extern uint8_t set_sinr;
extern uint8_t ue_connection_test;
extern uint8_t set_seed;
extern uint8_t target_dl_mcs;
extern uint8_t target_ul_mcs;
extern uint8_t abstraction_flag;
extern uint8_t ethernet_flag;
extern uint16_t Nid_cell;

double cpuf;
#include "threads_t.h"
threads_t threads= {-1,-1,-1,-1,-1,-1,-1};

//#ifdef XFORMS
int otg_enabled;
int xforms=0;
//#endif

time_stats_t oaisim_stats;
time_stats_t oaisim_stats_f;
time_stats_t dl_chan_stats;
time_stats_t ul_chan_stats;

// this should reflect the channel models in openair1/SIMULATION/TOOLS/defs.h
mapping small_scale_names[] = {
  { "custom", custom }, { "SCM_A", SCM_A },
  { "SCM_B", SCM_B   }, { "SCM_C", SCM_C },
  { "SCM_D", SCM_D   }, { "EPA",   EPA   },
  { "EVA",   EVA     }, { "ETU",   ETU   },
  { "MBSFN", MBSFN },   { "Rayleigh8", Rayleigh8 },
  { "Rayleigh1", Rayleigh1 }, { "Rayleigh1_800", Rayleigh1_800 },
  { "Rayleigh1_corr", Rayleigh1_corr }, { "Rayleigh1_anticorr", Rayleigh1_anticorr },
  { "Rice8", Rice8 }, { "Rice1", Rice1 }, { "Rice1_corr", Rice1_corr },
  { "Rice1_anticorr", Rice1_anticorr }, { "AWGN", AWGN }, { NULL,-1 }
};
#if !defined(ENABLE_ITTI)
static void *
sigh (void *arg);
#endif
void
oai_shutdown (void);

void reset_opp_meas_oaisim (void);

void wait_eNBs(void)
{
  return;
}

void
help (void)
{
  printf ("Usage: oaisim -h -a -F -C tdd_config -K [log_file] -V [vcd_file] -R N_RB_DL -e -x transmission_mode -m target_dl_mcs -r(ate_adaptation) -n n_frames -s snr_dB -k ricean_factor -t max_delay -f forgetting factor -A channel_model -z cooperation_flag -u nb_local_ue -U UE mobility -b nb_local_enb -B eNB_mobility -M ethernet_flag -p nb_master -g multicast_group -l log_level -c ocg_enable -T traffic model -D multicast network device\n");

  printf ("-h provides this help message!\n");
  printf ("-a Activates PHY abstraction mode\n");
  printf ("-A set the multipath channel simulation,  options are: SCM_A, SCM_B, SCM_C, SCM_D, EPA, EVA, ETU, Rayleigh8, Rayleigh1, Rayleigh1_corr,Rayleigh1_anticorr, Rice8,, Rice1, AWGN \n");
  printf ("-b Set the number of local eNB\n");
  printf ("-B Set the mobility model for eNB, options are: STATIC, RWP, RWALK, \n");
  printf ("-c [1,2,3,4] Activate the config generator (OCG) to process the scenario descriptor, or give the scenario manually: -c template_1.xml \n");
  printf ("-C [0-6] Sets TDD configuration\n");
  printf ("-e Activates extended prefix mode\n");
  printf ("-E Random number generator seed\n");
  printf ("-f Set the forgetting factor for time-variation\n");
  printf ("-F Activates FDD transmission (TDD is default)\n");
  printf ("-g Set multicast group ID (0,1,2,3) - valid if M is set\n");
  printf ("-G Enable background traffic \n");
  printf ("-H Enable handover operation (default disabled) \n");
  printf ("-I Enable CLI interface (to connect use telnet localhost 1352)\n");
  printf ("-k Set the Ricean factor (linear)\n");
  printf ("-K [log_file] Enable ITTI logging into log_file\n");
  printf ("-l Set the global log level (8:trace, 7:debug, 6:info, 4:warn, 3:error) \n");
  printf ("-L [0-1] 0 to disable new link adaptation, 1 to enable new link adapatation\n");
  printf ("-m Gives a fixed DL mcs for eNB scheduler\n");
  printf ("-M Set the machine ID for Ethernet-based emulation\n");
  printf ("-n Set the number of frames for the simulation. 0 for no limit\n");
  printf ("-O [enb_conf_file] eNB configuration file name\n");
  printf ("-p Set the total number of machine in emulation - valid if M is set\n");
  printf ("-P [trace type] Enable protocol analyzer. Possible values for OPT:\n");
  printf ("    - wireshark: Enable tracing of layers above PHY using an UDP socket\n");
  printf ("    - pcap:      Enable tracing of layers above PHY to a pcap file\n");
  printf ("    - tshark:    Not implemented yet\n");
  printf ("-q Enable Openair performance profiler \n");
  printf ("-Q Activate and set the MBMS service: 0 : not used (default eMBMS disabled), 1: eMBMS and RRC Connection enabled, 2: eMBMS relaying and RRC Connection enabled, 3: eMBMS enabled, RRC Connection disabled, 4: eMBMS relaying enabled, RRC Connection disabled\n");
  printf ("-R [6,15,25,50,75,100] Sets N_RB_DL\n");
  printf ("-r Activates rate adaptation (DL for now)\n");
  printf ("-s snr_dB set a fixed (average) SNR, this deactivates the openair channel model generator (OCM)\n");
  printf ("-S snir_dB set a fixed (average) SNIR, this deactivates the openair channel model generator (OCM)\n");
  printf ("-t Gives a fixed UL mcs for eNB scheduler\n");
  printf ("-T activate the traffic generator. Valide options are m2m,scbr,mcbr,bcbr,auto_pilot,bicycle_race,open_arena,team_fortress,m2m_traffic,auto_pilot_l,auto_pilot_m,auto_pilot_h,auto_pilot_e,virtual_game_l,virtual_game_m,virtual_game_h,virtual_game_f,alarm_humidity,alarm_smoke,alarm_temperature,openarena_dl,openarena_ul,voip_g711,voip_g729,video_vbr_10mbps,video_vbr_4mbps,video_vbr_2mbp,video_vbr_768kbps,video_vbr_384kbps,video_vbr_192kpbs,background_users\n");
  printf ("-u Set the number of local UE\n");
  printf ("-U Set the mobility model for UE, options are: STATIC, RWP, RWALK\n");
  printf ("-V [vcd_file] Enable VCD dump into vcd_file\n");
  printf ("-w number of CBA groups, if not specified or zero, CBA is inactive\n");
#ifdef SMBV
  printf ("-W IP address to connect to Rohde&Schwarz SMBV100A and configure SMBV from config file. -W0 uses default IP 192.168.12.201\n");
#else
  printf ("-W [Rohde&Schwarz SMBV100A functions disabled. Recompile with SMBV=1]\n");
#endif
  printf ("-x deprecated. Set the transmission mode in config file!\n");
  printf ("-y Set the number of receive antennas at the UE (1 or 2)\n");
  printf ("-Y Set the global log verbosity (none, low, medium, high, full) \n");
  printf ("-z Set the cooperation flag (0 for no cooperation, 1 for delay diversity and 2 for distributed alamouti\n");
  printf ("-Z Reserved\n");
  printf ("--xforms Activate the grapical scope\n");

#if T_TRACER
  printf ("--T_port [port]    use given port\n");
  printf ("--T_nowait         don't wait for tracer, start immediately\n");
  printf ("--T_dont_fork      to ease debugging with gdb\n");
#endif
}

pthread_t log_thread;

void
log_thread_init (void)
{
  //create log_list
  //log_list_init(&log_list);
#ifndef LOG_NO_THREAD

  log_shutdown = 0;

  if ((pthread_mutex_init (&log_lock, NULL) != 0)
      || (pthread_cond_init (&log_notify, NULL) != 0)) {
    return;
  }

  if (pthread_create (&log_thread, NULL, log_thread_function, (void*) NULL)
      != 0) {
    log_thread_finalize ();
    return;
  }

#endif

}

//Call it after the last LOG call
int
log_thread_finalize (void)
{
  int err = 0;

#ifndef LOG_NO_THREAD

  if (pthread_mutex_lock (&log_lock) != 0) {
    return -1;
  }

  log_shutdown = 1;

  /* Wake up LOG thread */
  if ((pthread_cond_broadcast (&log_notify) != 0)
      || (pthread_mutex_unlock (&log_lock) != 0)) {
    err = -1;
  }

  if (pthread_join (log_thread, NULL) != 0) {
    err = -1;
  }

  if (pthread_mutex_unlock (&log_lock) != 0) {
    err = -1;
  }

  if (!err) {
    //log_list_free(&log_list);
    pthread_mutex_lock (&log_lock);
    pthread_mutex_destroy (&log_lock);
    pthread_cond_destroy (&log_notify);
  }

#endif

  return err;
}

#if defined(ENABLE_ITTI)
static void set_cli_start(module_id_t module_idP, uint8_t start)
{
  if (module_idP < NB_eNB_INST) {
    oai_emulation.info.cli_start_enb[module_idP] = start;
  } else {
    oai_emulation.info.cli_start_ue[module_idP - NB_eNB_INST] = start;
  }
}
#endif

#ifdef OPENAIR2
int omv_write(int pfd, node_list* enb_node_list, node_list* ue_node_list, Data_Flow_Unit omv_data)
{
  module_id_t i;
  omv_data.end = 0;

  //omv_data.total_num_nodes = NB_UE_INST + NB_eNB_INST;
  for (i = 0; i < NB_eNB_INST; i++) {
    if (enb_node_list != NULL) {
      omv_data.geo[i].x = (enb_node_list->node->x_pos < 0.0) ? 0.0 : enb_node_list->node->x_pos;
      omv_data.geo[i].y = (enb_node_list->node->y_pos < 0.0) ? 0.0 : enb_node_list->node->y_pos;
      omv_data.geo[i].z = 1.0;
      omv_data.geo[i].mobility_type = oai_emulation.info.omg_model_enb;
      omv_data.geo[i].node_type = 0; //eNB
      enb_node_list = enb_node_list->next;
      omv_data.geo[i].Neighbors = 0;
/*
      for (j = NB_RU; j < NB_UE_INST + NB_RU; j++) {
        if (is_UE_active (i, j - NB_RU) == 1) {
          omv_data.geo[i].Neighbor[omv_data.geo[i].Neighbors] = j;
          omv_data.geo[i].Neighbors++;
          LOG_D(
		OMG,
		"[RU %d][UE %d] is_UE_active(i,j) %d geo (x%d, y%d) num neighbors %d\n", i, j-NB_RU, is_UE_active(i,j-NB_RU), omv_data.geo[i].x, omv_data.geo[i].y, omv_data.geo[i].Neighbors);
        }
      }
*/
    }
  }

  for (i = NB_RU; i < NB_UE_INST + NB_RU; i++) {
    if (ue_node_list != NULL) {
      omv_data.geo[i].x = (ue_node_list->node->x_pos < 0.0) ? 0.0 : ue_node_list->node->x_pos;
      omv_data.geo[i].y = (ue_node_list->node->y_pos < 0.0) ? 0.0 : ue_node_list->node->y_pos;
      omv_data.geo[i].z = 1.0;
      omv_data.geo[i].mobility_type = oai_emulation.info.omg_model_ue;
      omv_data.geo[i].node_type = 1; //UE
      //trial
      omv_data.geo[i].state = 1;
      omv_data.geo[i].rnti = 88;
      omv_data.geo[i].connected_eNB = 0;
      omv_data.geo[i].RSRP = 66;
      omv_data.geo[i].RSRQ = 55;
      omv_data.geo[i].Pathloss = 44;
      omv_data.geo[i].RSSI[0] = 33;
      omv_data.geo[i].RSSI[1] = 22;

      if ((sizeof(omv_data.geo[0].RSSI) / sizeof(omv_data.geo[0].RSSI[0])) > 2) {
        omv_data.geo[i].RSSI[2] = 11;
      }

      ue_node_list = ue_node_list->next;
      omv_data.geo[i].Neighbors = 0;
/*
      for (j = 0; j < NB_RU; j++) {
        if (is_UE_active (j, i - NB_RU) == 1) {
          omv_data.geo[i].Neighbor[omv_data.geo[i].Neighbors] = j;
          omv_data.geo[i].Neighbors++;
          LOG_D(
		OMG,
		"[UE %d][RU %d] is_UE_active  %d geo (x%d, y%d) num neighbors %d\n", i-NB_RU, j, is_UE_active(j,i-NB_RU), omv_data.geo[i].x, omv_data.geo[i].y, omv_data.geo[i].Neighbors);
        }
      }
*/
    }
  }

  LOG_E(OMG, "pfd %d \n", pfd);

  if (write (pfd, &omv_data, sizeof(struct Data_Flow_Unit)) == -1)
    perror ("write omv failed");

  return 1;
}

void omv_end(int pfd, Data_Flow_Unit omv_data)
{
  omv_data.end = 1;

  if (write (pfd, &omv_data, sizeof(struct Data_Flow_Unit)) == -1)
    perror ("write omv failed");
}
#endif

#ifdef OPENAIR2
int pfd[2]; // fd for omv : fixme: this could be a local var
#endif

#ifdef OPENAIR2
static Data_Flow_Unit omv_data;
#endif //ALU
static module_id_t UE_inst = 0;
static module_id_t eNB_inst = 0;
static module_id_t ru_id;

Packet_OTG_List_t *otg_pdcp_buffer;

typedef enum l2l1_task_state_e {
  L2L1_WAITTING, L2L1_RUNNING, L2L1_TERMINATED,
} l2l1_task_state_t;

l2l1_task_state_t l2l1_state = L2L1_WAITTING;

extern openair0_timestamp current_ru_rx_timestamp[NUMBER_OF_RU_MAX][MAX_NUM_CCs];
extern openair0_timestamp current_UE_rx_timestamp[NUMBER_OF_UE_MAX][MAX_NUM_CCs];
extern openair0_timestamp last_eNB_rx_timestamp[NUMBER_OF_eNB_MAX][MAX_NUM_CCs];
extern openair0_timestamp last_UE_rx_timestamp[NUMBER_OF_UE_MAX][MAX_NUM_CCs];

/*------------------------------------------------------------------------------*/
void *
l2l1_task (void *args_p)
{

  int CC_id;

  // Framing variables
  int32_t sf;

  //char fname[64], vname[64];

  //#ifdef XFORMS
  // current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0)
  // at eNB 0, an UL scope for every UE
  FD_lte_phy_scope_ue *form_ue[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
  FD_lte_phy_scope_enb *form_enb[NUMBER_OF_UE_MAX];
  char title[255];
  char xname[32] = "oaisim";
  int xargc = 1;
  char *xargv[1];
  //#endif

#undef PRINT_STATS /* this undef is to avoid gcc warnings */
#define PRINT_STATS
#ifdef PRINT_STATS
  //int len;
  FILE *UE_stats[NUMBER_OF_UE_MAX];
  FILE *UE_stats_th[NUMBER_OF_UE_MAX];
  FILE *eNB_stats[NUMBER_OF_eNB_MAX];
  FILE *eNB_avg_thr;
  FILE *eNB_l2_stats;
  char UE_stats_filename[255];
  char eNB_stats_filename[255];
  char UE_stats_th_filename[255];
  char eNB_stats_th_filename[255];
#endif

  if (xforms==1) {
    xargv[0] = xname;
    fl_initialize (&xargc, xargv, NULL, 0, 0);
    eNB_inst = 0;
    for (UE_inst = 0; UE_inst < NB_UE_INST; UE_inst++) {
      for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
	// DL scope at UEs
	form_ue[CC_id][UE_inst] = create_lte_phy_scope_ue();
	sprintf (title, "LTE DL SCOPE eNB %d to UE %d CC_id %d", eNB_inst, UE_inst, CC_id);
	fl_show_form (form_ue[CC_id][UE_inst]->lte_phy_scope_ue, FL_PLACE_HOTSPOT, FL_FULLBORDER, title);

	if (PHY_vars_UE_g[UE_inst][CC_id]->use_ia_receiver == 1) {
	  fl_set_button(form_ue[CC_id][UE_inst]->button_0,1);
	  fl_set_object_label(form_ue[CC_id][UE_inst]->button_0, "IA Receiver ON");
	  fl_set_object_color(form_ue[CC_id][UE_inst]->button_0, FL_GREEN, FL_GREEN);
	}

      }
    }
  }

#ifdef PRINT_STATS

  for (UE_inst=0; UE_inst<NB_UE_INST; UE_inst++) {
    sprintf(UE_stats_filename,"UE_stats%d.txt",UE_inst);
    UE_stats[UE_inst] = fopen (UE_stats_filename, "w");
  }

  for (eNB_inst=0; eNB_inst<NB_eNB_INST; eNB_inst++) {
    sprintf(eNB_stats_filename,"eNB_stats%d.txt",eNB_inst);
    eNB_stats[eNB_inst] = fopen (eNB_stats_filename, "w");
  }

  if(abstraction_flag==0) {
    for (UE_inst=0; UE_inst<NB_UE_INST; UE_inst++) {
      /* TODO: transmission_mode is defined per CC, we set 0 for now */
      sprintf(UE_stats_th_filename,"UE_stats_th%d_tx%d.txt",UE_inst,oai_emulation.info.transmission_mode[0]);
      UE_stats_th[UE_inst] = fopen (UE_stats_th_filename, "w");
    }

    /* TODO: transmission_mode is defined per CC, we set 0 for now */
    sprintf(eNB_stats_th_filename,"eNB_stats_th_tx%d.txt",oai_emulation.info.transmission_mode[0]);
    eNB_avg_thr = fopen (eNB_stats_th_filename, "w");
  } else {
    for (UE_inst=0; UE_inst<NB_UE_INST; UE_inst++) {
      /* TODO: transmission_mode is defined per CC, we set 0 for now */
      sprintf(UE_stats_th_filename,"UE_stats_abs_th%d_tx%d.txt",UE_inst,oai_emulation.info.transmission_mode[0]);
      UE_stats_th[UE_inst] = fopen (UE_stats_th_filename, "w");
    }

    /* TODO: transmission_mode is defined per CC, we set 0 for now */
    sprintf(eNB_stats_th_filename,"eNB_stats_abs_th_tx%d.txt",oai_emulation.info.transmission_mode[0]);
    eNB_avg_thr = fopen (eNB_stats_th_filename, "w");
  }

#ifdef OPENAIR2
  eNB_l2_stats = fopen ("eNB_l2_stats.txt", "w");
  LOG_I(EMU,"eNB_l2_stats=%p\n", eNB_l2_stats);
#endif

#endif

#if defined(ENABLE_ITTI)
  MessageDef *message_p = NULL;
  const char *msg_name = NULL;
  int result;

  itti_mark_task_ready (TASK_L2L1);
  LOG_I(EMU, "TASK_L2L1 is READY\n");

  if ((oai_emulation.info.nb_enb_local > 0) &&
      (oai_emulation.info.node_function[0] < NGFI_RAU_IF4p5)) {
    /* Wait for the initialize message */
    do {
      if (message_p != NULL) {
        result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
        AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
      }

      itti_receive_msg (TASK_L2L1, &message_p);
      msg_name = ITTI_MSG_NAME (message_p);
      LOG_I(EMU, "TASK_L2L1 received %s in state L2L1_WAITTING\n", msg_name);

      switch (ITTI_MSG_ID(message_p)) {
      case INITIALIZE_MESSAGE:
        l2l1_state = L2L1_RUNNING;
        start_eNB = 1;
        break;

      case ACTIVATE_MESSAGE:
        set_cli_start(ITTI_MSG_INSTANCE (message_p), 1);
        break;

      case DEACTIVATE_MESSAGE:
        set_cli_start(ITTI_MSG_INSTANCE (message_p), 0);
        break;

      case TERMINATE_MESSAGE:
        l2l1_state = L2L1_TERMINATED;
        break;

      default:
        LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
        break;
      }
    } while (l2l1_state == L2L1_WAITTING);

    result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
  }

#endif
  module_id_t UE_id;

  if (abstraction_flag == 1) {
    for (UE_id = 0; UE_id < NB_UE_INST; UE_id++)
      dl_phy_sync_success (UE_id, 0, 0,1);   //UE_id%NB_eNB_INST);
  }

  start_meas (&oaisim_stats);

  for (frame = 0;
       (l2l1_state != L2L1_TERMINATED) &&
	 ((oai_emulation.info.n_frames_flag == 0) ||
	  (frame < oai_emulation.info.n_frames));
       frame++) {

#if defined(ENABLE_ITTI)

    do {
      // Checks if a message has been sent to L2L1 task
      itti_poll_msg (TASK_L2L1, &message_p);

      if (message_p != NULL) {
        msg_name = ITTI_MSG_NAME (message_p);
        LOG_I(EMU, "TASK_L2L1 received %s\n", msg_name);

        switch (ITTI_MSG_ID(message_p)) {
        case ACTIVATE_MESSAGE:
          set_cli_start(ITTI_MSG_INSTANCE (message_p), 1);
          break;

        case DEACTIVATE_MESSAGE:
          set_cli_start(ITTI_MSG_INSTANCE (message_p), 0);
          break;

        case TERMINATE_MESSAGE:
          l2l1_state = L2L1_TERMINATED;
          break;

        case MESSAGE_TEST:
          break;

        default:
          LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
          break;
        }

        result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
        AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
      }
    } while(message_p != NULL);

#endif

    //Run the aperiodic user-defined events
    if (oai_emulation.info.oeh_enabled == 1)
      execute_events (frame);

    if (ue_connection_test == 1) {
      if ((frame % 20) == 0) {
        snr_dB += snr_direction;
        sinr_dB -= snr_direction;
      }

      if (snr_dB == -20) {
        snr_direction = snr_step;
      } else if (snr_dB == 20) {
        snr_direction = -snr_step;
      }
    }

    oai_emulation.info.frame = frame;
    //oai_emulation.info.time_ms += 1;
    oai_emulation.info.time_s += 0.01; // emu time in s, each frame lasts for 10 ms // JNote: TODO check the coherency of the time and frame (I corrected it to 10 (instead of 0.01)

    update_omg (frame); // frequency is defined in the omg_global params configurable by the user
    update_omg_ocm ();

#ifdef OPENAIR2

    // check if pipe is still open
    if ((oai_emulation.info.omv_enabled == 1)) {
      omv_write (pfd[1], enb_node_list, ue_node_list, omv_data);
    }

#endif

    for (sf = 0; sf < 10; sf++) {
      LOG_D(EMU,"************************* Subframe %d\n",sf);
      start_meas (&oaisim_stats_f);

      wait_for_slot_isr ();

#if defined(ENABLE_ITTI)
      itti_update_lte_time(frame % MAX_FRAME_NUMBER, sf<<1);
#endif

      oai_emulation.info.time_ms = frame * 10 + sf;

#ifdef PROC

    if(Channel_Flag==1)
      Channel_Func(s_re2,s_im2,r_re2,r_im2,r_re02,r_im02,r_re0_d,r_im0_d,r_re0_u,r_im0_u,RU2UE,UE2RU,enb_data,ue_data,abstraction_flag,frame_parms,sf<<1);

    if(Channel_Flag==0)
#endif
      { // SUBFRAME INNER PART
#if defined(ENABLE_ITTI)
        log_set_instance_type (LOG_INSTANCE_ENB);
#endif

	CC_id=0;
        int all_done=0;

        while (all_done==0) {

          pthread_mutex_lock(&subframe_mutex);
          int subframe_ru_mask_local = subframe_ru_mask;
          int subframe_UE_mask_local  = subframe_UE_mask;
          pthread_mutex_unlock(&subframe_mutex);
          LOG_D(EMU,"Frame %d, Subframe %d, NB_RU %d, NB_UE %d: Checking masks %x,%x\n",frame,sf,NB_RU,NB_UE_INST,subframe_ru_mask_local,subframe_UE_mask_local);
          if ((subframe_ru_mask_local == ((1<<NB_RU)-1)) &&
              (subframe_UE_mask_local == ((1<<NB_UE_INST)-1)))
             all_done=1;
          else
	    usleep(1500);
        }

        //clear subframe masks for next round
        pthread_mutex_lock(&subframe_mutex);
        subframe_ru_mask=0;
        subframe_UE_mask=0;
        pthread_mutex_unlock(&subframe_mutex);

        // increment timestamps
	/*
        for (ru_id = oai_emulation.info.first_enb_local;
             (ru_id
              < (oai_emulation.info.first_enb_local
                 + oai_emulation.info.nb_enb_local));
             ru_id++) {
	*/
	for (ru_id=0;ru_id<NB_RU;ru_id++) {
	  current_ru_rx_timestamp[ru_id][CC_id] += RC.ru[ru_id]->frame_parms.samples_per_tti;
	  LOG_D(EMU,"RU %d/%d: TS %"PRIi64"\n",ru_id,CC_id,current_ru_rx_timestamp[ru_id][CC_id]);
        }
        for (UE_inst = 0; UE_inst<NB_UE_INST;UE_inst++) {
	  current_UE_rx_timestamp[UE_inst][CC_id] += PHY_vars_UE_g[UE_inst][CC_id]->frame_parms.samples_per_tti;
	  LOG_D(EMU,"UE %d/%d: TS %"PRIi64"\n",UE_inst,CC_id,current_UE_rx_timestamp[UE_inst][CC_id]);
        }

        for (eNB_inst = oai_emulation.info.first_enb_local;
             (eNB_inst
              < (oai_emulation.info.first_enb_local
                 + oai_emulation.info.nb_enb_local));
             eNB_inst++) {
          if (oai_emulation.info.cli_start_enb[eNB_inst] != 0) {

	    /*
	    LOG_D(EMU,
		  "PHY procedures eNB %d for frame %d, subframe %d TDD %d/%d Nid_cell %d\n",
		  eNB_inst,
		  frame % MAX_FRAME_NUMBER,
		  sf,
		  PHY_vars_eNB_g[eNB_inst][0]->frame_parms.frame_type,
		  PHY_vars_eNB_g[eNB_inst][0]->frame_parms.tdd_config,
		  PHY_vars_eNB_g[eNB_inst][0]->frame_parms.Nid_cell);

	    */
#ifdef OPENAIR2
	    //Application: traffic gen
            update_otg_eNB (eNB_inst, oai_emulation.info.time_ms);

            //IP/OTG to PDCP and PDCP to IP operation
            //        pdcp_run (frame, 1, 0, eNB_inst); //PHY_vars_eNB_g[eNB_id]->Mod_id
#endif

#ifdef PRINT_STATS

            if((sf==9) && frame%10==0)
              if(eNB_avg_thr)
                fprintf(eNB_avg_thr,"%d %d\n",RC.eNB[eNB_inst][0]->proc.proc_rxtx[sf&1].frame_tx,
                        (RC.eNB[eNB_inst][0]->total_system_throughput)/((RC.eNB[eNB_inst][0]->proc.proc_rxtx[sf&1].frame_tx+1)*10));
	    /*
            if (eNB_stats[eNB_inst]) {
              len = dump_eNB_stats(RC.eNB[eNB_inst][0], stats_buffer, 0);
              rewind (eNB_stats[eNB_inst]);
              fwrite (stats_buffer, 1, len, eNB_stats[eNB_inst]);
              fflush(eNB_stats[eNB_inst]);
            }
	    */
#ifdef OPENAIR2
/*
            if (eNB_l2_stats) {
              len = dump_eNB_l2_stats (stats_buffer, 0);
              rewind (eNB_l2_stats);
              fwrite (stats_buffer, 1, len, eNB_l2_stats);
              fflush(eNB_l2_stats);
            }
*/

#endif
#endif
          }
        }// eNB_inst loop

#if defined(ENABLE_ITTI)
        log_set_instance_type (LOG_INSTANCE_UE);
#endif

	if ((sf == 0) && ((frame % MAX_FRAME_NUMBER) == 0) && (abstraction_flag == 0)
	    && (oai_emulation.info.n_frames == 1)) {

	  write_output ("dlchan0.m",
			"dlch0",
			&(PHY_vars_UE_g[0][0]->common_vars.common_vars_rx_data_per_thread[0].dl_ch_estimates[0][0][0]),
			(6
			 * (PHY_vars_UE_g[0][0]->frame_parms.ofdm_symbol_size)),
			1, 1);
	  write_output ("dlchan1.m",
			"dlch1",
			&(PHY_vars_UE_g[0][0]->common_vars.common_vars_rx_data_per_thread[0].dl_ch_estimates[1][0][0]),
			(6
			 * (PHY_vars_UE_g[0][0]->frame_parms.ofdm_symbol_size)),
			1, 1);
	  write_output ("dlchan2.m",
			"dlch2",
			&(PHY_vars_UE_g[0][0]->common_vars.common_vars_rx_data_per_thread[0].dl_ch_estimates[2][0][0]),
			(6
			 * (PHY_vars_UE_g[0][0]->frame_parms.ofdm_symbol_size)),
			1, 1);
	  write_output ("pbch_rxF_comp0.m",
			"pbch_comp0",
			PHY_vars_UE_g[0][0]->pbch_vars[0]->rxdataF_comp[0],
			6 * 12 * 4, 1, 1);
	  write_output ("pbch_rxF_llr.m", "pbch_llr",
			PHY_vars_UE_g[0][0]->pbch_vars[0]->llr,
			(PHY_vars_UE_g[0][0]->frame_parms.Ncp == 0) ? 1920 : 1728, 1,
			4);
	}

	stop_meas (&oaisim_stats_f);
      } // SUBFRAME INNER PART

    }
    update_ocm ();
    /*
    if ((frame >= 10) && (frame <= 11) && (abstraction_flag == 0)
#ifdef PROC
	&&(Channel_Flag==0)
#endif
	) {
      sprintf (fname, "UEtxsig%d.m", frame % MAX_FRAME_NUMBER);
      sprintf (vname, "txs%d", frame % MAX_FRAME_NUMBER);
      write_output (fname,
		    vname,
		    PHY_vars_UE_g[0][0]->common_vars.txdata[0],
		    PHY_vars_UE_g[0][0]->frame_parms.samples_per_tti
		    * 10,
		    1, 1);
      sprintf (fname, "eNBtxsig%d.m", frame % MAX_FRAME_NUMBER);
      sprintf (vname, "txs%d", frame % MAX_FRAME_NUMBER);
      write_output (fname,
		    vname,
		    PHY_vars_eNB_g[0][0]->common_vars.txdata[0][0],
		    PHY_vars_UE_g[0][0]->frame_parms.samples_per_tti
		    * 10,
		    1, 1);
      sprintf (fname, "eNBtxsigF%d.m", frame % MAX_FRAME_NUMBER);
      sprintf (vname, "txsF%d", frame % MAX_FRAME_NUMBER);
      write_output (fname,
		    vname,
		    PHY_vars_eNB_g[0][0]->common_vars.txdataF[0][0],
		    PHY_vars_eNB_g[0][0]->frame_parms.symbols_per_tti
		    * PHY_vars_eNB_g[0][0]->frame_parms.ofdm_symbol_size,
		    1, 1);
      sprintf (fname, "UErxsig%d.m", frame % MAX_FRAME_NUMBER);
      sprintf (vname, "rxs%d", frame % MAX_FRAME_NUMBER);
      write_output (fname,
		    vname,
		    PHY_vars_UE_g[0][0]->common_vars.rxdata[0],
		    PHY_vars_UE_g[0][0]->frame_parms.samples_per_tti
		    * 10,
		    1, 1);
      sprintf (fname, "eNBrxsig%d.m", frame % MAX_FRAME_NUMBER);
      sprintf (vname, "rxs%d", frame % MAX_FRAME_NUMBER);
      write_output (fname,
		    vname,
		    PHY_vars_eNB_g[0][0]->common_vars.rxdata[0][0],
		    PHY_vars_UE_g[0][0]->frame_parms.samples_per_tti
		    * 10,
		    1, 1);
    }
    */

    //#ifdef XFORMS
    if (xforms==1) {
      eNB_inst = 0;

      for (UE_inst = 0; UE_inst < NB_UE_INST; UE_inst++) {
	for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
	  phy_scope_UE(form_ue[CC_id][UE_inst],
		   PHY_vars_UE_g[UE_inst][CC_id],
		   eNB_inst,
		   UE_inst,
		   7);
	}
	if (RC.eNB && RC.eNB[eNB_inst] && RC.eNB[eNB_inst][0] )
	  phy_scope_eNB(form_enb[UE_inst],
			RC.eNB[eNB_inst][0],
			UE_inst);

      }
    }
    //#endif

#ifdef SMBV

    // Rohde&Schwarz SMBV100A vector signal generator
    if ((frame % MAX_FRAME_NUMBER == config_frames[0]) || (frame % MAX_FRAME_NUMBER == config_frames[1]) || (frame % MAX_FRAME_NUMBER == config_frames[2]) || (frame % MAX_FRAME_NUMBER == config_frames[3])) {
      smbv_frame_cnt++;
    }

#endif

  } // frame loop

  stop_meas (&oaisim_stats);
  oai_shutdown ();

#ifdef PRINT_STATS

  for (UE_inst=0; UE_inst<NB_UE_INST; UE_inst++) {
    if (UE_stats[UE_inst])
      fclose (UE_stats[UE_inst]);

    if(UE_stats_th[UE_inst])
      fclose (UE_stats_th[UE_inst]);
  }

  for (eNB_inst=0; eNB_inst<NB_eNB_INST; eNB_inst++) {
    if (eNB_stats[eNB_inst])
      fclose (eNB_stats[eNB_inst]);
  }

  if (eNB_avg_thr)
    fclose (eNB_avg_thr);

  if (eNB_l2_stats)
    fclose (eNB_l2_stats);

#endif

#if defined(ENABLE_ITTI)
  itti_terminate_tasks(TASK_L2L1);
#endif

  return NULL;
}

/*
 * The following two functions are meant to restart *the lte-softmodem* and are
 * here to make oaisim compile. A restart command from the controller will be
 * ignored in oaisim.
 */
int stop_L1L2(int enb_id)
{
  LOG_W(FLEXRAN_AGENT, "stop_L1L2() not supported in oaisim\n");
  return 0;
}

int restart_L1L2(int enb_id)
{
  LOG_W(FLEXRAN_AGENT, "restart_L1L2() not supported in oaisim\n");
  return 0;
}

#if T_TRACER
int T_wait = 1;       /* by default we wait for the tracer */
int T_port = 2021;    /* default port to listen to to wait for the tracer */
int T_dont_fork = 0;  /* default is to fork, see 'T_init' to understand */
#endif

void wait_RUs(void)
{
  int i;

  // wait for all RUs to be configured over fronthaul
  pthread_mutex_lock(&RC.ru_mutex);

  while (RC.ru_mask>0) {
    pthread_cond_wait(&RC.ru_cond,&RC.ru_mutex);
  }

  // copy frame parameters from RU to UEs
  for (i=0;i<NB_UE_INST;i++) {
    PHY_vars_UE_g[i][0]->frame_parms.N_RB_DL              = RC.ru[0]->frame_parms.N_RB_DL;
    PHY_vars_UE_g[i][0]->frame_parms.N_RB_UL              = RC.ru[0]->frame_parms.N_RB_UL;
    PHY_vars_UE_g[i][0]->frame_parms.nb_antennas_tx       = 1;
    PHY_vars_UE_g[i][0]->frame_parms.nb_antennas_rx       = 1;
    // set initially to 2, it will be revised after initial synchronization
    PHY_vars_UE_g[i][0]->frame_parms.nb_antenna_ports_eNB = 2;
    PHY_vars_UE_g[i][0]->frame_parms.tdd_config = 1;
    PHY_vars_UE_g[i][0]->frame_parms.dl_CarrierFreq       = RC.ru[0]->frame_parms.dl_CarrierFreq;
    PHY_vars_UE_g[i][0]->frame_parms.ul_CarrierFreq       = RC.ru[0]->frame_parms.ul_CarrierFreq;
    PHY_vars_UE_g[i][0]->frame_parms.eutra_band           = RC.ru[0]->frame_parms.eutra_band;
    LOG_I(PHY,"Initializing UE %d frame parameters from RU information: N_RB_DL %d, p %d, dl_Carrierfreq %u, ul_CarrierFreq %u, eutra_band %d\n",
	  i,
	  PHY_vars_UE_g[i][0]->frame_parms.N_RB_DL,
	  PHY_vars_UE_g[i][0]->frame_parms.nb_antenna_ports_eNB,
	  PHY_vars_UE_g[i][0]->frame_parms.dl_CarrierFreq,
	  PHY_vars_UE_g[i][0]->frame_parms.ul_CarrierFreq,
	  PHY_vars_UE_g[i][0]->frame_parms.eutra_band);

    current_UE_rx_timestamp[i][0] = RC.ru[0]->frame_parms.samples_per_tti + RC.ru[0]->frame_parms.ofdm_symbol_size + RC.ru[0]->frame_parms.nb_prefix_samples0;

  }

  for (ru_id=0;ru_id<RC.nb_RU;ru_id++) current_ru_rx_timestamp[ru_id][0] = RC.ru[ru_id]->frame_parms.samples_per_tti;

  printf("RUs are ready, let's go\n");
}

void init_UE(int,int,int,int);
void init_RU(const char*);

void set_UE_defaults(int nb_ue) {

  for (int UE_id = 0;UE_id<nb_ue;UE_id++) {
    for (int CC_id = 0;CC_id<MAX_NUM_CCs;CC_id++) {
      for (uint8_t i=0; i<RX_NB_TH_MAX; i++) {
	PHY_vars_UE_g[UE_id][CC_id]->pdcch_vars[i][0]->dciFormat      = 0;
	PHY_vars_UE_g[UE_id][CC_id]->pdcch_vars[i][0]->agregationLevel      = 0xFF;
      }
      PHY_vars_UE_g[UE_id][CC_id]->current_dlsch_cqi[0] = 10;
    }
  }
}

static void print_current_directory(void)
{
  char dir[8192]; /* arbitrary size (should be big enough) */
  if (getcwd(dir, 8192) == NULL)
    printf("ERROR getting working directory\n");
  else
    printf("working directory: %s\n", dir);
}

void init_devices(void);

int main (int argc, char **argv)
{

  clock_t t;

  print_current_directory();

  start_background_system();

#ifdef SMBV
  // Rohde&Schwarz SMBV100A vector signal generator
  strcpy(smbv_ip,DEFAULT_SMBV_IP);
#endif

#ifdef PROC
  int node_id;
  int port,Process_Flag=0,wgt,Channel_Flag=0,temp;
#endif

  //default parameters
  oai_emulation.info.n_frames = MAX_FRAME_NUMBER; //1024;          //10;
  oai_emulation.info.n_frames_flag = 0; //fixme
  snr_dB = 30;

  //Default values if not changed by the user in get_simulation_options();
  pdcp_period = 1;
  omg_period = 1;
  //Clean ip rule table
  for(int i =0; i<NUMBER_OF_UE_MAX; i++){
      char command_line[100];
      sprintf(command_line, "while ip rule del table %d; do true; done",i+201);
      /* we don't care about return value from system(), but let's the
       * compiler be silent, so let's do "if (XX);"
       */
      if (system(command_line)) /* nothing */;
  }
  // start thread for log gen
  log_thread_init ();

  init_oai_emulation (); // to initialize everything !!!

  // get command-line options
  get_simulation_options (argc, argv); //Command-line options

#if T_TRACER
  T_init(T_port, T_wait, T_dont_fork);
#endif

  // Initialize VCD LOG module
  VCD_SIGNAL_DUMPER_INIT (oai_emulation.info.vcd_file);

#if !defined(ENABLE_ITTI)
  pthread_t tid;
  int err;
  sigset_t sigblock;
  sigemptyset (&sigblock);
  sigaddset (&sigblock, SIGHUP);
  sigaddset (&sigblock, SIGINT);
  sigaddset (&sigblock, SIGTERM);
  sigaddset (&sigblock, SIGQUIT);
  //sigaddset(&sigblock, SIGKILL);

  if ((err = pthread_sigmask (SIG_BLOCK, &sigblock, NULL)) != 0) {
    printf ("SIG_BLOCK error\n");
    return -1;
  }

  if (pthread_create (&tid, NULL, sigh, NULL)) {
    printf ("Pthread for tracing Signals is not created!\n");
    return -1;
  } else {
    printf ("Pthread for tracing Signals is created!\n");
  }

#endif
  // configure oaisim with OCG
  oaisim_config (); // config OMG and OCG, OPT, OTG, OLG

  if (ue_connection_test == 1) {
    snr_direction = -snr_step;
    snr_dB = 20;
    sinr_dB = -20;
  }

  pthread_cond_init(&sync_cond,NULL);
  pthread_mutex_init(&sync_mutex, NULL);
  pthread_mutex_init(&subframe_mutex, NULL);

#ifdef OPENAIR2
  init_omv ();
#endif
  //Before this call, NB_UE_INST and NB_eNB_INST are not set correctly
  check_and_adjust_params ();

  set_seed = oai_emulation.emulation_config.seed.value;

  init_otg_pdcp_buffer ();

  init_seed (set_seed);

  init_RU(NULL);

  init_devices ();

  //  init_openair2 ();
  //  init_openair0();

  if (create_tasks_ue(oai_emulation.info.nb_ue_local) < 0)
      exit(-1); // need a softer mode

  printf("Waiting for RUs to get set up\n");
  wait_RUs();

  init_UE(NB_UE_INST,0,0,1);

  set_UE_defaults(NB_UE_INST);

  init_ocm ();
  printf("Sending sync to all threads\n");

  pthread_mutex_lock(&sync_mutex);
  sync_var=0;
  pthread_cond_broadcast(&sync_cond);
  pthread_mutex_unlock(&sync_mutex);

#ifdef SMBV
  // Rohde&Schwarz SMBV100A vector signal generator
  smbv_init_config(smbv_fname, smbv_nframes);
  smbv_write_config_from_frame_parms(smbv_fname, &PHY_vars_eNB_g[0][0]->frame_parms);
#endif

  /* #if defined (FLEXRAN_AGENT_SB_IF)
  flexran_agent_start();
  #endif */

  // add events to future event list: Currently not used
  //oai_emulation.info.oeh_enabled = 1;
  if (oai_emulation.info.oeh_enabled == 1)
    schedule_events ();

  // oai performance profiler is enabled
  if (oai_emulation.info.opp_enabled == 1)
    reset_opp_meas_oaisim ();

  cpuf=get_cpu_freq_GHz();

  init_time ();

  init_slot_isr ();

  t = clock ();

  LOG_N(EMU,
        ">>>>>>>>>>>>>>>>>>>>>>>>>>> OAIEMU initialization done <<<<<<<<<<<<<<<<<<<<<<<<<<\n\n");

#ifndef PACKAGE_VERSION
#  define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
#endif
  LOG_I(EMU, "Version: %s\n", PACKAGE_VERSION);

#if defined(ENABLE_ITTI)

  // Handle signals until all tasks are terminated
  itti_wait_tasks_end();

#else

  if (oai_emulation.info.nb_enb_local > 0) {
    eNB_app_task (NULL); // do nothing for the moment
  }

  l2l1_task (NULL);
#endif
  t = clock () - t;
  LOG_I(EMU, "Duration of the simulation: %f seconds\n",
        ((float) t) / CLOCKS_PER_SEC);

  LOG_N(EMU,
        ">>>>>>>>>>>>>>>>>>>>>>>>>>> OAIEMU Ending <<<<<<<<<<<<<<<<<<<<<<<<<<\n\n");

  raise (SIGINT);
  //  oai_shutdown ();

  return (0);
}

void
reset_opp_meas_oaisim (void)
{
  uint8_t eNB_id = 0, UE_id = 0;

  reset_meas (&oaisim_stats);
  reset_meas (&oaisim_stats_f); // frame

  // init time stats here (including channel)
  reset_meas (&dl_chan_stats);
  reset_meas (&ul_chan_stats);

  for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) {
    reset_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc[0]);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc[1]);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc_rx[0]);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc_rx[1]);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc_tx);

    //    reset_meas (&PHY_vars_UE_g[UE_id][0]->ofdm_demod_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->rx_dft_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_channel_estimation_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_freq_offset_estimation_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_decoding_stats[0]);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_decoding_stats[1]);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_rate_unmatching_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_turbo_decoding_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_deinterleaving_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_llr_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_unscrambling_stats);

    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_init_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_alpha_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_beta_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_gamma_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_ext_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_intl1_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_intl2_stats);

    reset_meas (&PHY_vars_UE_g[UE_id][0]->tx_prach);

    reset_meas (&PHY_vars_UE_g[UE_id][0]->ofdm_mod_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_encoding_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_modulation_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_segmentation_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_rate_matching_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_turbo_encoding_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_interleaving_stats);
    reset_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_multiplexing_stats);

    /*
     * L2 functions
     */

    // UE MAC
    reset_meas (&UE_mac_inst[UE_id].ue_scheduler); // total
    reset_meas (&UE_mac_inst[UE_id].tx_ulsch_sdu); // inlcude rlc_data_req + mac header gen
    reset_meas (&UE_mac_inst[UE_id].rx_dlsch_sdu); // include mac_rrc_data_ind or mac_rlc_status_ind+mac_rlc_data_ind and  mac header parser
    reset_meas (&UE_mac_inst[UE_id].ue_query_mch);
    reset_meas (&UE_mac_inst[UE_id].rx_mch_sdu); // include rld_data_ind+ parse mch header
    reset_meas (&UE_mac_inst[UE_id].rx_si); // include rlc_data_ind + mac header parser

    reset_meas (&UE_pdcp_stats[UE_id].pdcp_run);
    reset_meas (&UE_pdcp_stats[UE_id].data_req);
    reset_meas (&UE_pdcp_stats[UE_id].data_ind);
    reset_meas (&UE_pdcp_stats[UE_id].apply_security);
    reset_meas (&UE_pdcp_stats[UE_id].validate_security);
    reset_meas (&UE_pdcp_stats[UE_id].pdcp_ip);
    reset_meas (&UE_pdcp_stats[UE_id].ip_pdcp);

  }

  for (eNB_id = 0; eNB_id < NB_eNB_INST; eNB_id++) {

    for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) {
      reset_meas (&RU2UE[eNB_id][UE_id][0]->random_channel);
      reset_meas (&RU2UE[eNB_id][UE_id][0]->interp_time);
      reset_meas (&RU2UE[eNB_id][UE_id][0]->interp_freq);
      reset_meas (&RU2UE[eNB_id][UE_id][0]->convolution);
      reset_meas (&UE2RU[UE_id][eNB_id][0]->random_channel);
      reset_meas (&UE2RU[UE_id][eNB_id][0]->interp_time);
      reset_meas (&UE2RU[UE_id][eNB_id][0]->interp_freq);
      reset_meas (&UE2RU[UE_id][eNB_id][0]->convolution);
    }

    reset_meas (&RC.eNB[eNB_id][0]->phy_proc);
    reset_meas (&RC.eNB[eNB_id][0]->phy_proc_rx);
    reset_meas (&RC.eNB[eNB_id][0]->phy_proc_tx);
    reset_meas (&RC.eNB[eNB_id][0]->rx_prach);

    reset_meas (&RC.eNB[eNB_id][0]->ofdm_mod_stats);
    reset_meas (&RC.eNB[eNB_id][0]->dlsch_encoding_stats);
    reset_meas (&RC.eNB[eNB_id][0]->dlsch_modulation_stats);
    reset_meas (&RC.eNB[eNB_id][0]->dlsch_scrambling_stats);
    reset_meas (&RC.eNB[eNB_id][0]->dlsch_rate_matching_stats);
    reset_meas (&RC.eNB[eNB_id][0]->dlsch_turbo_encoding_stats);
    reset_meas (&RC.eNB[eNB_id][0]->dlsch_interleaving_stats);

    //    reset_meas (&RC.eNB[eNB_id][0]->ofdm_demod_stats);
    //reset_meas(&RC.eNB[eNB_id]->rx_dft_stats);
    //reset_meas(&RC.eNB[eNB_id]->ulsch_channel_estimation_stats);
    //reset_meas(&RC.eNB[eNB_id]->ulsch_freq_offset_estimation_stats);
    reset_meas (&RC.eNB[eNB_id][0]->ulsch_decoding_stats);
    reset_meas (&RC.eNB[eNB_id][0]->ulsch_demodulation_stats);
    reset_meas (&RC.eNB[eNB_id][0]->ulsch_rate_unmatching_stats);
    reset_meas (&RC.eNB[eNB_id][0]->ulsch_turbo_decoding_stats);
    reset_meas (&RC.eNB[eNB_id][0]->ulsch_deinterleaving_stats);
    reset_meas (&RC.eNB[eNB_id][0]->ulsch_demultiplexing_stats);
    reset_meas (&RC.eNB[eNB_id][0]->ulsch_llr_stats);
    reset_meas (&RC.eNB[eNB_id][0]->ulsch_tc_init_stats);
    reset_meas (&RC.eNB[eNB_id][0]->ulsch_tc_alpha_stats);
    reset_meas (&RC.eNB[eNB_id][0]->ulsch_tc_beta_stats);
    reset_meas (&RC.eNB[eNB_id][0]->ulsch_tc_gamma_stats);
    reset_meas (&RC.eNB[eNB_id][0]->ulsch_tc_ext_stats);
    reset_meas (&RC.eNB[eNB_id][0]->ulsch_tc_intl1_stats);
    reset_meas (&RC.eNB[eNB_id][0]->ulsch_tc_intl2_stats);
#ifdef LOCALIZATION
    reset_meas(&RC.eNB[eNB_id][0]->localization_stats);
#endif

    /*
     * L2 functions
     */
    // eNB MAC
    reset_meas (&RC.mac[eNB_id]->eNB_scheduler); // total
    reset_meas (&RC.mac[eNB_id]->schedule_si); // only schedule + tx
    reset_meas (&RC.mac[eNB_id]->schedule_ra); // only ra
    reset_meas (&RC.mac[eNB_id]->schedule_ulsch); // onlu ulsch
    reset_meas (&RC.mac[eNB_id]->fill_DLSCH_dci); // only dci
    reset_meas (&RC.mac[eNB_id]->schedule_dlsch_preprocessor); // include rlc_data_req + MAC header gen
    reset_meas (&RC.mac[eNB_id]->schedule_dlsch); // include rlc_data_req + MAC header gen + pre-processor
    reset_meas (&RC.mac[eNB_id]->schedule_mch); // only embms
    reset_meas (&RC.mac[eNB_id]->rx_ulsch_sdu); // include rlc_data_ind + mac header parser

    reset_meas (&eNB_pdcp_stats[eNB_id].pdcp_run);
    reset_meas (&eNB_pdcp_stats[eNB_id].data_req);
    reset_meas (&eNB_pdcp_stats[eNB_id].data_ind);
    reset_meas (&eNB_pdcp_stats[eNB_id].apply_security);
    reset_meas (&eNB_pdcp_stats[eNB_id].validate_security);
    reset_meas (&eNB_pdcp_stats[eNB_id].pdcp_ip);
    reset_meas (&eNB_pdcp_stats[eNB_id].ip_pdcp);

  }
}

void
print_opp_meas_oaisim (void)
{

  uint8_t eNB_id = 0, UE_id = 0;

  print_meas (&oaisim_stats, "[OAI][total_exec_time]", &oaisim_stats,
              &oaisim_stats);
  print_meas (&oaisim_stats_f, "[OAI][SF_exec_time]", &oaisim_stats,
              &oaisim_stats_f);

  print_meas (&dl_chan_stats, "[DL][chan_stats]", &oaisim_stats,
              &oaisim_stats_f);
  print_meas (&ul_chan_stats, "[UL][chan_stats]", &oaisim_stats,
              &oaisim_stats_f);

  for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) {
    for (ru_id = 0; ru_id < NB_RU; ru_id++) {
      print_meas (&RU2UE[ru_id][UE_id][0]->random_channel,
                  "[DL][random_channel]", &oaisim_stats, &oaisim_stats_f);
      print_meas (&RU2UE[ru_id][UE_id][0]->interp_time,
                  "[DL][interp_time]", &oaisim_stats, &oaisim_stats_f);
      print_meas (&RU2UE[ru_id][UE_id][0]->interp_freq,
                  "[DL][interp_freq]", &oaisim_stats, &oaisim_stats_f);
      print_meas (&RU2UE[ru_id][UE_id][0]->convolution,
                  "[DL][convolution]", &oaisim_stats, &oaisim_stats_f);

      print_meas (&UE2RU[UE_id][ru_id][0]->random_channel,
                  "[UL][random_channel]", &oaisim_stats, &oaisim_stats_f);
      print_meas (&UE2RU[UE_id][ru_id][0]->interp_time,
                  "[UL][interp_time]", &oaisim_stats, &oaisim_stats_f);
      print_meas (&UE2RU[UE_id][ru_id][0]->interp_freq,
                  "[UL][interp_freq]", &oaisim_stats, &oaisim_stats_f);
      print_meas (&UE2RU[UE_id][ru_id][0]->convolution,
                  "[UL][convolution]", &oaisim_stats, &oaisim_stats_f);
    }
  }

  for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) {
    print_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc[0], "[UE][total_phy_proc[0]]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc[1], "[UE][total_phy_proc[1]]",
                &oaisim_stats, &oaisim_stats_f);

    print_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc_rx[0],
                "[UE][total_phy_proc_rx[0]]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc_rx[1],
                "[UE][total_phy_proc_rx[1]]", &oaisim_stats, &oaisim_stats_f);
    //    print_meas (&PHY_vars_UE_g[UE_id][0]->ofdm_demod_stats,
    //                "[UE][ofdm_demod]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->rx_dft_stats, "[UE][rx_dft]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_channel_estimation_stats,
                "[UE][channel_est]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_freq_offset_estimation_stats,
                "[UE][freq_offset]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_llr_stats, "[UE][llr]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_unscrambling_stats,
                "[UE][unscrambling]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_decoding_stats[0],
                "[UE][decoding[0]]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_decoding_stats[1],
                "[UE][decoding[1]]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_rate_unmatching_stats,
                "[UE][rate_unmatching]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_deinterleaving_stats,
                "[UE][deinterleaving]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_turbo_decoding_stats,
                "[UE][turbo_decoding]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_init_stats,
                "[UE][ |_tc_init]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_alpha_stats,
                "[UE][ |_tc_alpha]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_beta_stats,
                "[UE][ |_tc_beta]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_gamma_stats,
                "[UE][ |_tc_gamma]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_ext_stats,
                "[UE][ |_tc_ext]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_intl1_stats,
                "[UE][ |_tc_intl1]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->dlsch_tc_intl2_stats,
                "[UE][ |_tc_intl2]", &oaisim_stats, &oaisim_stats_f);

    print_meas (&PHY_vars_UE_g[UE_id][0]->phy_proc_tx,
                "[UE][total_phy_proc_tx]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->ofdm_mod_stats, "[UE][ofdm_mod]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_modulation_stats,
                "[UE][modulation]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_encoding_stats,
                "[UE][encoding]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_segmentation_stats,
                "[UE][segmentation]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_rate_matching_stats,
                "[UE][rate_matching]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_turbo_encoding_stats,
                "[UE][turbo_encoding]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_interleaving_stats,
                "[UE][interleaving]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&PHY_vars_UE_g[UE_id][0]->ulsch_multiplexing_stats,
                "[UE][multiplexing]", &oaisim_stats, &oaisim_stats_f);

  }

  for (eNB_id = 0; eNB_id < NB_eNB_INST; eNB_id++) {
    print_meas (&RC.eNB[eNB_id][0]->phy_proc,
                "[eNB][total_phy_proc]", &oaisim_stats, &oaisim_stats_f);

    print_meas (&RC.eNB[eNB_id][0]->phy_proc_tx,
                "[eNB][total_phy_proc_tx]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&RC.eNB[eNB_id][0]->ofdm_mod_stats,
                "[eNB][ofdm_mod]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&RC.eNB[eNB_id][0]->dlsch_modulation_stats,
                "[eNB][modulation]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&RC.eNB[eNB_id][0]->dlsch_scrambling_stats,
                "[eNB][scrambling]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&RC.eNB[eNB_id][0]->dlsch_encoding_stats,
                "[eNB][encoding]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&RC.eNB[eNB_id][0]->dlsch_interleaving_stats,
                "[eNB][|_interleaving]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&RC.eNB[eNB_id][0]->dlsch_rate_matching_stats,
                "[eNB][|_rate_matching]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&RC.eNB[eNB_id][0]->dlsch_turbo_encoding_stats,
                "[eNB][|_turbo_encoding]", &oaisim_stats, &oaisim_stats_f);

    print_meas (&RC.eNB[eNB_id][0]->phy_proc_rx,
                "[eNB][total_phy_proc_rx]", &oaisim_stats, &oaisim_stats_f);
    //    print_meas (&RC.eNB[eNB_id][0]->ofdm_demod_stats,
    //                "[eNB][ofdm_demod]", &oaisim_stats, &oaisim_stats_f);
    //print_meas(&RC.eNB[eNB_id][0]->ulsch_channel_estimation_stats,"[eNB][channel_est]");
    //print_meas(&RC.eNB[eNB_id][0]->ulsch_freq_offset_estimation_stats,"[eNB][freq_offset]");
    //print_meas(&RC.eNB[eNB_id][0]->rx_dft_stats,"[eNB][rx_dft]");
    print_meas (&RC.eNB[eNB_id][0]->ulsch_demodulation_stats,
                "[eNB][demodulation]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&RC.eNB[eNB_id][0]->ulsch_decoding_stats,
                "[eNB][decoding]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&RC.eNB[eNB_id][0]->ulsch_deinterleaving_stats,
                "[eNB][|_deinterleaving]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&RC.eNB[eNB_id][0]->ulsch_demultiplexing_stats,
                "[eNB][|_demultiplexing]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&RC.eNB[eNB_id][0]->ulsch_rate_unmatching_stats,
                "[eNB][|_rate_unmatching]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&RC.eNB[eNB_id][0]->ulsch_turbo_decoding_stats,
                "[eNB][|_turbo_decoding]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&RC.eNB[eNB_id][0]->ulsch_tc_init_stats,
                "[eNB][ |_tc_init]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&RC.eNB[eNB_id][0]->ulsch_tc_alpha_stats,
                "[eNB][ |_tc_alpha]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&RC.eNB[eNB_id][0]->ulsch_tc_beta_stats,
                "[eNB][ |_tc_beta]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&RC.eNB[eNB_id][0]->ulsch_tc_gamma_stats,
                "[eNB][ |_tc_gamma]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&RC.eNB[eNB_id][0]->ulsch_tc_ext_stats,
                "[eNB][ |_tc_ext]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&RC.eNB[eNB_id][0]->ulsch_tc_intl1_stats,
                "[eNB][ |_tc_intl1]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&RC.eNB[eNB_id][0]->ulsch_tc_intl2_stats,
                "[eNB][ |_tc_intl2]", &oaisim_stats, &oaisim_stats_f);

    print_meas (&RC.eNB[eNB_id][0]->rx_prach, "[eNB][rx_prach]",
                &oaisim_stats, &oaisim_stats_f);

#ifdef LOCALIZATION
    print_meas(&RC.eNB[eNB_id][0]->localization_stats, "[eNB][LOCALIZATION]",&oaisim_stats,&oaisim_stats_f);
#endif
  }

  for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) {

    print_meas (&UE_mac_inst[UE_id].ue_scheduler, "[UE][mac_scheduler]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&UE_mac_inst[UE_id].tx_ulsch_sdu, "[UE][tx_ulsch_sdu]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&UE_mac_inst[UE_id].rx_dlsch_sdu, "[UE][rx_dlsch_sdu]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&UE_mac_inst[UE_id].ue_query_mch, "[UE][query_MCH]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&UE_mac_inst[UE_id].rx_mch_sdu, "[UE][rx_mch_sdu]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&UE_mac_inst[UE_id].rx_si, "[UE][rx_si]", &oaisim_stats,
                &oaisim_stats_f);

    print_meas (&UE_pdcp_stats[UE_id].pdcp_run, "[UE][total_pdcp_run]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&UE_pdcp_stats[UE_id].data_req, "[UE][DL][pdcp_data_req]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&UE_pdcp_stats[UE_id].data_ind, "[UE][UL][pdcp_data_ind]",
                &oaisim_stats, &oaisim_stats_f);

    print_meas (&UE_pdcp_stats[UE_id].apply_security,
                "[UE][DL][apply_security]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&UE_pdcp_stats[UE_id].validate_security,
                "[UE][UL][validate_security]", &oaisim_stats,
                &oaisim_stats_f);
    print_meas (&UE_pdcp_stats[UE_id].ip_pdcp, "[UE][DL][ip_pdcp]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&UE_pdcp_stats[UE_id].pdcp_ip, "[UE][UL][pdcp_ip]",
                &oaisim_stats, &oaisim_stats_f);

  }

  for (eNB_id = 0; eNB_id < NB_eNB_INST; eNB_id++) {

    print_meas (&RC.mac[eNB_id]->eNB_scheduler, "[eNB][mac_scheduler]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&RC.mac[eNB_id]->schedule_si, "[eNB][DL][SI]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&RC.mac[eNB_id]->schedule_ra, "[eNB][DL][RA]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&RC.mac[eNB_id]->fill_DLSCH_dci,
                "[eNB][DL/UL][fill_DCI]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&RC.mac[eNB_id]->schedule_dlsch_preprocessor,
                "[eNB][DL][preprocessor]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&RC.mac[eNB_id]->schedule_dlsch,
                "[eNB][DL][schedule_tx_dlsch]", &oaisim_stats,
                &oaisim_stats_f);
    print_meas (&RC.mac[eNB_id]->schedule_mch, "[eNB][DL][mch]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&RC.mac[eNB_id]->schedule_ulsch, "[eNB][UL][ULSCH]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&RC.mac[eNB_id]->rx_ulsch_sdu,
                "[eNB][UL][rx_ulsch_sdu]", &oaisim_stats, &oaisim_stats_f);

    print_meas (&eNB_pdcp_stats[eNB_id].pdcp_run, "[eNB][pdcp_run]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&eNB_pdcp_stats[eNB_id].data_req,
                "[eNB][DL][pdcp_data_req]", &oaisim_stats, &oaisim_stats_f);
    print_meas (&eNB_pdcp_stats[eNB_id].data_ind,
                "[eNB][UL][pdcp_data_ind]", &oaisim_stats, &oaisim_stats_f);

    print_meas (&eNB_pdcp_stats[eNB_id].apply_security,
                "[eNB][DL][apply_security]", &oaisim_stats,
                &oaisim_stats_f);
    print_meas (&eNB_pdcp_stats[eNB_id].validate_security,
                "[eNB][UL][validate_security]", &oaisim_stats,
                &oaisim_stats_f);
    print_meas (&eNB_pdcp_stats[eNB_id].ip_pdcp, "[eNB][DL][ip_pdcp]",
                &oaisim_stats, &oaisim_stats_f);
    print_meas (&eNB_pdcp_stats[eNB_id].pdcp_ip, "[eNB][UL][pdcp_ip]",
                &oaisim_stats, &oaisim_stats_f);

  }

}

#if !defined(ENABLE_ITTI)
static void *
sigh (void *arg)
{

  int signum;
  sigset_t sigcatch;
  sigemptyset (&sigcatch);
  sigaddset (&sigcatch, SIGHUP);
  sigaddset (&sigcatch, SIGINT);
  sigaddset (&sigcatch, SIGTERM);
  sigaddset (&sigcatch, SIGQUIT);

  for (;;) {
    sigwait (&sigcatch, &signum);

    //sigwait(&sigblock, &signum);
    switch (signum) {
    case SIGHUP:
    case SIGINT:
    case SIGTERM:
    case SIGQUIT:
      fprintf (stderr, "received signal %d \n", signum);
      // no need for mutx: when ITTI not used, this variable is only accessed by this function
      l2l1_state = L2L1_TERMINATED;
      break;

    default:
      fprintf (stderr, "Unexpected signal %d \n", signum);
      exit (-1);
      break;
    }
  }

  pthread_exit (NULL);
}
#endif /* !defined(ENABLE_ITTI) */

void
oai_shutdown (void)
{
  static int done = 0;

  if (done)
    return;

  free (otg_pdcp_buffer);
  otg_pdcp_buffer = 0;

#ifdef SMBV

  // Rohde&Schwarz SMBV100A vector signal generator
  if (config_smbv) {
    smbv_send_config (smbv_fname,smbv_ip);
  }

#endif

  //Perform KPI measurements
  if (oai_emulation.info.otg_enabled == 1){
    LOG_N(EMU,"calling OTG kpi gen .... \n");
    kpi_gen ();
  }
  if (oai_emulation.info.opp_enabled == 1)
    print_opp_meas_oaisim ();

#ifdef PROC

  if (abstraction_flag == 0 && Channel_Flag==0 && Process_Flag==0)
#else
    if (abstraction_flag == 0)
#endif
      {
	/*
	  #ifdef IFFT_FPGA
	  free(txdataF2[0]);
	  free(txdataF2[1]);
	  free(txdataF2);
	  free(txdata[0]);
	  free(txdata[1]);
	  free(txdata);
	  #endif
	*/
	/*
	for (int i = 0; i < 2; i++) {
	  free (s_re[i]);
	  free (s_im[i]);
	  free (r_re[i]);
	  free (r_im[i]);
	}

	free (s_re);
	free (s_im);
	free (r_re);
	free (r_im);
	s_re = 0;
	s_im = 0;
	r_re = 0;
	r_im = 0;*/

	lte_sync_time_free ();
      }

  // added for PHY abstraction
  if (oai_emulation.info.ocm_enabled == 1) {
    for (eNB_inst = 0; eNB_inst < NUMBER_OF_eNB_MAX; eNB_inst++) {
      free (enb_data[eNB_inst]);
      enb_data[eNB_inst] = 0;
    }

    for (UE_inst = 0; UE_inst < NUMBER_OF_UE_MAX; UE_inst++) {
      free (ue_data[UE_inst]);
      ue_data[UE_inst] = 0;
    }
  } //End of PHY abstraction changes

  // stop OMG
  stop_mobility_generator (omg_param_list); //omg_param_list.mobility_type
#ifdef OPENAIR2

  if (oai_emulation.info.omv_enabled == 1)
    omv_end (pfd[1], omv_data);

#endif

  if ((oai_emulation.info.ocm_enabled == 1) && (ethernet_flag == 0)
      && (ShaF != NULL)) {
    destroyMat (ShaF, map1, map2);
    ShaF = 0;
  }

  if (opt_enabled == 1)
    terminate_opt ();

  if (oai_emulation.info.cli_enabled)
    cli_server_cleanup ();

  for (int i = 0; i < NUMBER_OF_eNB_MAX + NUMBER_OF_UE_MAX; i++)
    if (oai_emulation.info.oai_ifup[i] == 1) {
      char interfaceName[8];
      snprintf (interfaceName, sizeof(interfaceName), "oai%d", i);
      bringInterfaceUp (interfaceName, 0);
    }

  log_thread_finalize ();
  logClean ();
  VCD_SIGNAL_DUMPER_CLOSE ();

  done = 1; // prevent next invokation of this function

  LOG_N(EMU,
        ">>>>>>>>>>>>>>>>>>>>>>>>>>> OAIEMU shutdown <<<<<<<<<<<<<<<<<<<<<<<<<<\n\n");
}

eNB_MAC_INST*
get_eNB_mac_inst (module_id_t module_idP)
{
  return (RC.mac[module_idP]);
}

OAI_Emulation*
get_OAI_emulation ()
{
  return &oai_emulation;
}

// dummy function declarations

void *rrc_enb_task(void *args_p)
{
  return NULL;
}

ext: c

max_stars_repo_name: davidraditya/OAI-Powder

max_issues_repo_name: davidraditya/OAI-Powder

max_forks_repo_name: davidraditya/OAI-Powder


text:
#pragma once

#include <math.h>
#include <stdint.h>

#include <gsl/gsl_matrix.h>
#include <gsl/gsl_vector.h>

double nn_sigmoid(const double x);
double nn_sigmoid_prime(const double x);

gsl_vector * nn_ones_v(const size_t n);
gsl_vector * nn_sigmoid_v(const gsl_vector *x);
gsl_vector * nn_sigmoid_prime_v(const gsl_vector *x);

gsl_matrix * nn_ones_m(const size_t n, const size_t m);
gsl_matrix * nn_sigmoid_m(const gsl_matrix *x);
gsl_matrix * nn_sigmoid_prime_m(const gsl_matrix *x);

ext: h

max_stars_repo_name: mygulamali/neural-net

max_issues_repo_name: mygulamali/neural-net

max_forks_repo_name: mygulamali/neural-net


text:
/* specfunc/test_gamma.c
 *
 * Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/* Author:  G. Jungman */

#include <config.h>
#include <gsl/gsl_test.h>
#include <gsl/gsl_sf.h>
#include "test_sf.h"

int test_gamma(void)
{
  gsl_sf_result r;
  gsl_sf_result r1, r2;
  double sgn;
  int s = 0;

  TEST_SF(s,  gsl_sf_lngamma_e, (-0.1, &r), 2.368961332728788655 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_lngamma_e, (-1.0/256.0, &r), 5.547444766967471595  , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_lngamma_e, (1.0e-08, &r), 18.420680738180208905 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_lngamma_e, (0.1, &r), 2.252712651734205 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_lngamma_e, (1.0 + 1.0/256.0, &r), -0.0022422226599611501448 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_lngamma_e, (2.0 + 1.0/256.0, &r), 0.0016564177556961728692 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_lngamma_e, (100.0, &r), 359.1342053695753 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_lngamma_e, (-1.0-1.0/65536.0, &r), 11.090348438090047844 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_lngamma_e, (-1.0-1.0/268435456.0, &r), 19.408121054103474300 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_lngamma_e, (-100.5, &r), -364.9009683094273518 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_lngamma_e, (-100-1.0/65536.0, &r), -352.6490910117097874 , TEST_TOL0, GSL_SUCCESS);

  TEST_SF_SGN(s, gsl_sf_lngamma_sgn_e, (0.7, &r, &sgn), 0.26086724653166651439, TEST_TOL1, 1.0, GSL_SUCCESS);
  TEST_SF_SGN(s, gsl_sf_lngamma_sgn_e, (0.1, &r, &sgn), 2.2527126517342059599, TEST_TOL0, 1.0, GSL_SUCCESS);
  TEST_SF_SGN(s, gsl_sf_lngamma_sgn_e, (-0.1, &r, &sgn), 2.368961332728788655, TEST_TOL0, -1.0, GSL_SUCCESS);
  TEST_SF_SGN(s, gsl_sf_lngamma_sgn_e, (-1.0-1.0/65536.0, &r, &sgn), 11.090348438090047844, TEST_TOL0, 1.0, GSL_SUCCESS);
  TEST_SF_SGN(s, gsl_sf_lngamma_sgn_e, (-2.0-1.0/256.0, &r, &sgn), 4.848447725860607213, TEST_TOL0, -1.0, GSL_SUCCESS);
  TEST_SF_SGN(s, gsl_sf_lngamma_sgn_e, (-2.0-1.0/65536.0, &r, &sgn), 10.397193628164674967, TEST_TOL0, -1.0, GSL_SUCCESS);
  TEST_SF_SGN(s, gsl_sf_lngamma_sgn_e, (-3.0-1.0/8.0, &r, &sgn), 0.15431112768404182427, TEST_TOL2, 1.0, GSL_SUCCESS);
  TEST_SF_SGN(s, gsl_sf_lngamma_sgn_e, (-100.5, &r, &sgn), -364.9009683094273518, TEST_TOL0, -1.0, GSL_SUCCESS);

  TEST_SF(s,  gsl_sf_gamma_e, (1.0 + 1.0/4096.0, &r), 0.9998591371459403421 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_gamma_e, (1.0 + 1.0/32.0, &r), 0.9829010992836269148 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_gamma_e, (2.0 + 1.0/256.0, &r), 1.0016577903733583299 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_gamma_e, (9.0, &r), 40320.0                   , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_gamma_e, (10.0, &r), 362880.0                  , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_gamma_e, (100.0, &r), 9.332621544394415268e+155 , TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_gamma_e, (170.0, &r), 4.269068009004705275e+304 , TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_gamma_e, (-10.5, &r), -2.640121820547716316e-07  , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_gamma_e, (-11.25, &r), 6.027393816261931672e-08  , TEST_TOL0, GSL_SUCCESS); /* exp()... not my fault */
  TEST_SF(s,  gsl_sf_gamma_e, (-1.0+1.0/65536.0, &r), -65536.42280587818970 , TEST_TOL0, GSL_SUCCESS);

  TEST_SF(s,  gsl_sf_gammastar_e, (1.0e-08, &r), 3989.423555759890865  , TEST_TOL1, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_gammastar_e, (1.0e-05, &r), 126.17168469882690233 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_gammastar_e, (0.001, &r), 12.708492464364073506 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_gammastar_e, (1.5, &r), 1.0563442442685598666 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_gammastar_e, (3.0, &r), 1.0280645179187893045 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_gammastar_e, (9.0, &r), 1.0092984264218189715 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_gammastar_e, (11.0, &r), 1.0076024283104962850 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_gammastar_e, (100.0, &r), 1.0008336778720121418 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_gammastar_e, (1.0e+05, &r), 1.0000008333336805529 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_gammastar_e, (1.0e+20, &r), 1.0 , TEST_TOL0, GSL_SUCCESS);

  TEST_SF(s,  gsl_sf_gammainv_e, (10.0, &r), 1.0/362880.0, TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_gammainv_e, (100.0, &r), 1.0715102881254669232e-156, TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_gammainv_e, (-10.5, &r), -1.0/2.640121820547716316e-07, TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_gammainv_e, (-11.25, &r), 1.0/6.027393816261931672e-08, TEST_TOL1, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_gammainv_e, (-1.0+1.0/65536.0, &r), -1.0/65536.42280587818970 , TEST_TOL1, GSL_SUCCESS);

  TEST_SF_2(s, gsl_sf_lngamma_complex_e, (5.0, 2.0, &r1, &r2),
            2.7487017561338026749, TEST_TOL0,
	    3.0738434100497007915, TEST_TOL0,
            GSL_SUCCESS);

  TEST_SF_2(s, gsl_sf_lngamma_complex_e, (100.0, 100.0, &r1, &r2),
            315.07804459949331323, TEST_TOL1,
	    2.0821801804113110099, TEST_TOL3,
            GSL_SUCCESS);

  TEST_SF_2(s, gsl_sf_lngamma_complex_e, (100.0, -1000.0, &r1, &r2),
            -882.3920483010362817000, TEST_TOL1,
	    -2.1169293725678813270, TEST_TOL3,
            GSL_SUCCESS);

  TEST_SF_2(s, gsl_sf_lngamma_complex_e, (-100.0, -1.0, &r1, &r2),
            -365.0362469529239516000, TEST_TOL1,
            -3.0393820262864361140, TEST_TOL1,
            GSL_SUCCESS);

  TEST_SF(s,  gsl_sf_taylorcoeff_e, (10,   1.0/1048576.0, &r), 1.7148961854776073928e-67  , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_taylorcoeff_e, (10,   1.0/1024.0, &r), 2.1738891788497900281e-37  , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_taylorcoeff_e, (10,   1.0, &r), 2.7557319223985890653e-07  , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_taylorcoeff_e, (10,   5.0, &r), 2.6911444554673721340      , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_taylorcoeff_e, (10,   500.0, &r), 2.6911444554673721340e+20  , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_taylorcoeff_e, (100,  100.0, &r), 1.0715102881254669232e+42  , TEST_TOL1, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_taylorcoeff_e, (1000, 200.0, &r), 2.6628790558154746898e-267 , TEST_TOL1, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_taylorcoeff_e, (1000, 500.0, &r), 2.3193170139740855074e+131 , TEST_TOL1, GSL_SUCCESS);

  TEST_SF(s,   gsl_sf_fact_e, (0, &r), 1.0 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,   gsl_sf_fact_e, (1, &r), 1.0 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,   gsl_sf_fact_e, (7, &r), 5040.0 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_fact_e, (33, &r), 8.683317618811886496e+36 , TEST_TOL0, GSL_SUCCESS);

  TEST_SF(s,   gsl_sf_doublefact_e, (0, &r), 1.0 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,   gsl_sf_doublefact_e, (1, &r), 1.0 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,   gsl_sf_doublefact_e, (7, &r), 105.0 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_doublefact_e, (33, &r), 6.332659870762850625e+18 , TEST_TOL0, GSL_SUCCESS);

  TEST_SF(s,  gsl_sf_lnfact_e, (0, &r), 0.0 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_lnfact_e, (1, &r), 0.0 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_lnfact_e, (7, &r), 8.525161361065414300 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_lnfact_e, (33, &r), 85.05446701758151741 , TEST_TOL0, GSL_SUCCESS);

  TEST_SF(s,  gsl_sf_lndoublefact_e, (0, &r), 0.0  , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_lndoublefact_e, (7, &r), 4.653960350157523371  , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_lndoublefact_e, (33, &r), 43.292252022541719660 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_lndoublefact_e, (34, &r), 45.288575519655959140 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_lndoublefact_e, (1034, &r), 3075.6383796271197707 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_lndoublefact_e, (1035, &r), 3078.8839081731809169 , TEST_TOL0, GSL_SUCCESS);

  TEST_SF(s,  gsl_sf_lnchoose_e, (7,3, &r), 3.555348061489413680 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_lnchoose_e, (5,2, &r), 2.302585092994045684 , TEST_TOL0, GSL_SUCCESS);

  TEST_SF(s,  gsl_sf_choose_e, (7,3, &r), 35.0 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_choose_e, (5,2, &r), 10.0 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_choose_e, (500,200, &r), 5.054949849935532221e+144 , TEST_TOL0, GSL_SUCCESS);

  TEST_SF(s,  gsl_sf_lnpoch_e, (5, 1.0/65536.0, &r), 0.000022981557571259389129, TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_lnpoch_e, (5, 1.0/256.0, &r),   0.005884960217985189004,    TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_lnpoch_e, (7,3, &r), 6.222576268071368616, TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_lnpoch_e, (5,2, &r), 3.401197381662155375, TEST_TOL0, GSL_SUCCESS);

  TEST_SF_SGN(s, gsl_sf_lnpoch_sgn_e, (-4.5, 0.25, &r, &sgn), 0.7430116475119920117, TEST_TOL1, 1.0, GSL_SUCCESS);
  TEST_SF_SGN(s, gsl_sf_lnpoch_sgn_e, (-4.5, 1.25, &r, &sgn), 2.1899306304483174731, TEST_TOL1, -1.0, GSL_SUCCESS);

  TEST_SF(s,  gsl_sf_poch_e, (7,3, &r), 504.0 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_poch_e, (5,2, &r), 30.0  , TEST_TOL1, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_poch_e, (5,1.0/256.0, &r), 1.0059023106151364982 , TEST_TOL0, GSL_SUCCESS);

  TEST_SF(s,  gsl_sf_pochrel_e, (7,3, &r), 503.0/3.0, TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_pochrel_e, (5,2, &r), 29.0/2.0, TEST_TOL1, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_pochrel_e, (5,0.01, &r), 1.5186393661368275330, TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_pochrel_e, (-5.5,0.01, &r), 1.8584945633829063516, TEST_TOL1, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_pochrel_e, (-5.5,-1.0/8.0, &r), 1.0883319303552135488, TEST_TOL1, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_pochrel_e, (-5.5,-1.0/256.0, &r), 1.7678268037726177453, TEST_TOL1, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_pochrel_e, (-5.5,-11.0, &r), 0.09090909090939652475, TEST_TOL0, GSL_SUCCESS);

  TEST_SF(s, gsl_sf_gamma_inc_P_e, (0.001, 0.001, &r), 0.9936876467088602902, TEST_TOL0, GSL_SUCCESS) ;
  TEST_SF(s, gsl_sf_gamma_inc_P_e, (0.001, 1.0, &r), 0.9997803916424144436, TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_gamma_inc_P_e, (0.001, 10.0, &r), 0.9999999958306921828, TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_gamma_inc_P_e, (1.0, 0.001, &r), 0.0009995001666250083319, TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_gamma_inc_P_e, (1.0, 1.01, &r), 0.6357810204284766802, TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_gamma_inc_P_e, (1.0, 10.0, &r), 0.9999546000702375151, TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_gamma_inc_P_e, (10.0, 10.01, &r), 0.5433207586693410570, TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_gamma_inc_P_e, (10.0, 20.0, &r), 0.9950045876916924128, TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_gamma_inc_P_e, (1000.0, 1000.1, &r), 0.5054666401440661753, TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_gamma_inc_P_e, (1000.0, 2000.0, &r), 1.0, TEST_TOL0, GSL_SUCCESS);

  TEST_SF(s, gsl_sf_gamma_inc_Q_e, (0.001, 0.001, &r), 0.006312353291139709793, TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_gamma_inc_Q_e, (0.001, 1.0, &r), 0.00021960835758555639171, TEST_TOL1, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_gamma_inc_Q_e, (0.001, 2.0, &r), 0.00004897691783098147880, TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_gamma_inc_Q_e, (0.001, 5.0, &r), 1.1509813397308608541e-06, TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_gamma_inc_Q_e, (1.0, 0.001, &r), 0.9990004998333749917, TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_gamma_inc_Q_e, (1.0, 1.01, &r), 0.3642189795715233198, TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_gamma_inc_Q_e, (1.0, 10.0, &r), 0.00004539992976248485154, TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_gamma_inc_Q_e, (10.0, 10.01, &r), 0.4566792413306589430, TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_gamma_inc_Q_e, (10.0, 100.0, &r), 1.1253473960842733885e-31, TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_gamma_inc_Q_e, (1000.0, 1000.1, &r), 0.4945333598559338247, TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_gamma_inc_Q_e, (1000.0, 2000.0, &r), 6.847349459614753180e-136, TEST_TOL2, GSL_SUCCESS);

  /* designed to trap the a-x=1 problem */
  TEST_SF(s, gsl_sf_gamma_inc_Q_e, (100,  99.0, &r), 0.5266956696005394, TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_gamma_inc_Q_e, (200, 199.0, &r), 0.5188414119121281, TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_gamma_inc_P_e, (100,  99.0, &r), 0.4733043303994607, TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_gamma_inc_P_e, (200, 199.0, &r), 0.4811585880878718, TEST_TOL2, GSL_SUCCESS);

  TEST_SF(s, gsl_sf_lnbeta_e, (1.0e-8, 1.0e-8, &r),  19.113827924512310617 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_lnbeta_e, (1.0e-8, 0.01, &r),  18.420681743788563403 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_lnbeta_e, (1.0e-8, 1.0, &r),  18.420680743952365472 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_lnbeta_e, (1.0e-8, 10.0, &r),  18.420680715662683009 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_lnbeta_e, (1.0e-8, 1000.0, &r),  18.420680669107656949 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_lnbeta_e, (0.1, 0.1, &r), 2.9813614810376273949 , TEST_TOL1, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_lnbeta_e, (0.1, 1.0, &r),  2.3025850929940456840 , TEST_TOL1, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_lnbeta_e, (0.1, 100.0, &r),  1.7926462324527931217 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_lnbeta_e, (0.1, 1000, &r),  1.5619821298353164928 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_lnbeta_e, (1.0, 1.00025, &r),  -0.0002499687552073570, TEST_TOL4, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_lnbeta_e, (1.0, 1.01, &r),  -0.009950330853168082848 , TEST_TOL3, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_lnbeta_e, (1.0, 1000.0, &r),  -6.907755278982137052 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_lnbeta_e, (100.0, 100.0, &r),  -139.66525908670663927 , TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_lnbeta_e, (100.0, 1000.0, &r),  -336.4348576477366051 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s, gsl_sf_lnbeta_e, (100.0, 1.0e+8, &r),  -1482.9339185256447309 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_beta_e, (1.0,   1.0, &r), 1.0                   , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_beta_e, (1.0, 1.001, &r), 0.9990009990009990010 , TEST_TOL0, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_beta_e, (1.0,   5.0, &r), 0.2                   , TEST_TOL1, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_beta_e, (1.0,  100.0, &r), 0.01                  , TEST_TOL1, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_beta_e, (10.0, 100.0, &r), 2.3455339739604649879e-15 , TEST_TOL2, GSL_SUCCESS);

  TEST_SF(s,  gsl_sf_beta_inc_e, (1.0, 1.0, 0.0, &r), 0.0, TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_beta_inc_e, (1.0, 1.0, 1.0, &r), 1.0, TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_beta_inc_e, (0.1, 0.1, 1.0, &r), 1.0, TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_beta_inc_e, ( 1.0,  1.0, 0.5, &r), 0.5, TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_beta_inc_e, ( 0.1,  1.0, 0.5, &r), 0.9330329915368074160, TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_beta_inc_e, (10.0,  1.0, 0.5, &r), 0.0009765625000000000000, TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_beta_inc_e, (50.0,  1.0, 0.5, &r), 8.881784197001252323e-16, TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_beta_inc_e, ( 1.0,  0.1, 0.5, &r), 0.06696700846319258402, TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_beta_inc_e, ( 1.0, 10.0, 0.5, &r), 0.99902343750000000000, TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_beta_inc_e, ( 1.0, 50.0, 0.5, &r), 0.99999999999999911180, TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_beta_inc_e, ( 1.0,  1.0, 0.1, &r), 0.10, TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_beta_inc_e, ( 1.0,  2.0, 0.1, &r), 0.19, TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_beta_inc_e, ( 1.0,  2.0, 0.9, &r), 0.99, TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_beta_inc_e, (50.0, 60.0, 0.5, &r), 0.8309072939016694143, TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_beta_inc_e, (90.0, 90.0, 0.5, &r), 0.5, TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_beta_inc_e, ( 500.0,  500.0, 0.6, &r), 0.9999999999157549630, TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_beta_inc_e, (5000.0, 5000.0, 0.4, &r), 4.518543727260666383e-91, TEST_TOL5, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_beta_inc_e, (5000.0, 5000.0, 0.6, &r), 1.0, TEST_TOL2, GSL_SUCCESS);
  TEST_SF(s,  gsl_sf_beta_inc_e, (5000.0, 2000.0, 0.6, &r), 8.445388773903332659e-89, TEST_TOL5, GSL_SUCCESS);

  return s;
}