diff --git a/openair1/PHY/TOOLS/time_meas.h b/openair1/PHY/TOOLS/time_meas.h index a732af69db96832ab792108947a1c2d03d3601e1..2ab84307404fc89c3d031d544ca700906eab3266 100644 --- a/openair1/PHY/TOOLS/time_meas.h +++ b/openair1/PHY/TOOLS/time_meas.h @@ -37,6 +37,8 @@ typedef struct { long long in; long long diff; + long long p_time; /*!< \brief absolute process duration */ + long long diff_square; /*!< \brief process duration square */ long long max; int trials; } time_stats_t; @@ -92,6 +94,9 @@ static inline void stop_meas(time_stats_t *ts) { #endif { ts->diff += (out-ts->in); + /// process duration is the difference between two clock points + ts->p_time = (out-ts->in); + ts->diff_square += pow((out-ts->in),2); if ((out-ts->in) > ts->max) ts->max = out-ts->in; @@ -104,6 +109,8 @@ static inline void reset_meas(time_stats_t *ts) { if (opp_enabled){ ts->trials=0; ts->diff=0; + ts->p_time=0; + ts->diff_square=0; ts->max=0; } } diff --git a/openair1/SIMULATION/LTE_PHY/Makefile b/openair1/SIMULATION/LTE_PHY/Makefile index 1f3f8f8e3c7b5e75ec957ae94667e67dc598f4b4..4b471c768a3cdf129009ecb8daa9c5106f578347 100644 --- a/openair1/SIMULATION/LTE_PHY/Makefile +++ b/openair1/SIMULATION/LTE_PHY/Makefile @@ -130,6 +130,8 @@ $(LFDS_DIR)/bin/liblfds611.a: test: $(SIMULATION_OBJS) $(TOOLS_OBJS) $(TOP_DIR)/PHY/INIT/lte_init.o test.c $(CC) test.c -I$(TOP_DIR) -o test $(CFLAGS) $(SIMULATION_OBJS) $(TOOLS_OBJS) -lm +OBJ += $(LIST_OBJ) +OBJ += $(MEM_OBJ) $(OBJ) : %.o : %.c @echo @echo Compiling $< ... diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c index 66e5c25d149ec2e3b6fbc3f81184ac244f652b9c..410290a0f4c00d37b9bc2b5333b02b1f981e0983 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim.c @@ -30,7 +30,7 @@ /*! \file dlsim.c \brief Top-level DL simulator \author R. Knopp - \date 2011 + \date 2011 - 2014 \version 0.1 \company Eurecom \email: knopp@eurecom.fr @@ -56,6 +56,7 @@ #include "OCG_vars.h" #include "UTIL/LOG/log.h" +#include "UTIL/LISTS/list.h" extern unsigned int dlsch_tbs25[27][25],TBStable[27][110]; extern unsigned char offset_mumimo_llr_drange_fix; @@ -85,6 +86,13 @@ PHY_VARS_eNB *PHY_vars_eNB; PHY_VARS_UE *PHY_vars_UE; int otg_enabled=0; +/*the following parameters are used to control the processing times calculations*/ +double t_tx_max = -1000000000; /*!< \brief initial max process time for tx */ +double t_rx_max = -1000000000; /*!< \brief initial max process time for rx */ +double t_tx_min = 1000000000; /*!< \brief initial min process time for tx */ +double t_rx_min = 1000000000; /*!< \brief initial min process time for rx */ +int n_tx_dropped = 0; /*!< \brief initial max process time for tx */ +int n_rx_dropped = 0; /*!< \brief initial max process time for rx */ void handler(int sig) { void *array[10]; @@ -1931,6 +1939,12 @@ int main(int argc, char **argv) { reset_meas(&PHY_vars_UE->dlsch_tc_ext_stats); reset_meas(&PHY_vars_UE->dlsch_tc_intl1_stats); reset_meas(&PHY_vars_UE->dlsch_tc_intl2_stats); + // initialization + struct list time_vector_tx; + initialize(&time_vector_tx); + struct list time_vector_rx; + initialize(&time_vector_rx); + for (trials = 0;trials<n_frames;trials++) { // printf("Trial %d\n",trials); fflush(stdout); @@ -3195,9 +3209,57 @@ PHY_vars_UE->lte_ue_pdcch_vars[0]->num_pdcch_symbols, PHY_vars_UE->frame_rx++; + + /* calculate the total processing time for each packet, + * get the max, min, and number of packets that exceed t>2000us + */ + double t_tx = (double)PHY_vars_eNB->phy_proc_tx.p_time/cpu_freq_GHz/1000.0; + double t_rx = (double)PHY_vars_UE->phy_proc_rx.p_time/cpu_freq_GHz/1000.0; + if (t_tx > t_tx_max) + t_tx_max = t_tx; + if (t_tx < t_tx_min) + t_tx_min = t_tx; + if (t_rx > t_rx_max) + t_rx_max = t_rx; + if (t_rx < t_rx_min) + t_rx_min = t_rx; + if (t_tx > 2000) + n_tx_dropped++; + if (t_rx > 2000) + n_rx_dropped++; + + push_front(&time_vector_tx, t_tx); + push_front(&time_vector_rx, t_rx); } //trials // round_trials[0]: number of code word : goodput the protocol - + double table_tx[time_vector_tx.size]; + totable(table_tx, &time_vector_tx); + + double table_rx[time_vector_rx.size]; + totable(table_rx, &time_vector_rx); + + // sort table + qsort (table_tx, time_vector_tx.size, sizeof(double), &compare); + qsort (table_rx, time_vector_rx.size, sizeof(double), &compare); +#ifdef DEBUG + int n; + printf("The transmitter raw data: \n"); + for (n=0; n< time_vector_tx.size; n++) + printf("%f ", table_tx[n]); + printf("\n"); + printf("The receiver raw data: \n"); + for (n=0; n< time_vector_rx.size; n++) + printf("%f ", table_rx[n]); + printf("\n"); +#endif + double tx_median = table_tx[time_vector_tx.size/2]; + double tx_q1 = table_tx[time_vector_tx.size/4]; + double tx_q3 = table_tx[3*time_vector_tx.size/4]; + + double rx_median = table_rx[time_vector_rx.size/2]; + double rx_q1 = table_rx[time_vector_rx.size/4]; + double rx_q3 = table_rx[3*time_vector_rx.size/4]; + effective_rate = ((double)(round_trials[0]-dci_errors)/((double)round_trials[0] + round_trials[1] + round_trials[2] + round_trials[3])); printf("\n**********************SNR = %f dB (tx_lev %f, sigma2_dB %f)**************************\n", @@ -3230,7 +3292,9 @@ PHY_vars_UE->lte_ue_pdcch_vars[0]->num_pdcch_symbols, if (print_perf==1) { printf("eNB TX function statistics (per 1ms subframe)\n\n"); + double std_phy_proc_tx = sqrt((double)PHY_vars_eNB->phy_proc_tx.diff_square/pow(cpu_freq_GHz,2)/pow(1000,2)/PHY_vars_eNB->phy_proc_tx.trials - pow((double)PHY_vars_eNB->phy_proc_tx.diff/PHY_vars_eNB->phy_proc_tx.trials/cpu_freq_GHz/1000,2)); printf("Total PHY proc tx :%f us (%d trials)\n",(double)PHY_vars_eNB->phy_proc_tx.diff/PHY_vars_eNB->phy_proc_tx.trials/cpu_freq_GHz/1000.0,PHY_vars_eNB->phy_proc_tx.trials); + printf("|__ Statistcs %f std: %fus max: %fus min: %fus median %fus q1 %fus q3 %fus n_dropped: %d packet \n",std_phy_proc_tx, t_tx_max, t_tx_min, tx_median, tx_q1, tx_q3, n_tx_dropped); printf("OFDM_mod time :%f us (%d trials)\n",(double)PHY_vars_eNB->ofdm_mod_stats.diff/PHY_vars_eNB->ofdm_mod_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_eNB->ofdm_mod_stats.trials); printf("DLSCH modulation time :%f us (%d trials)\n",(double)PHY_vars_eNB->dlsch_modulation_stats.diff/PHY_vars_eNB->dlsch_modulation_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_eNB->dlsch_modulation_stats.trials); printf("DLSCH scrambling time :%f us (%d trials)\n",(double)PHY_vars_eNB->dlsch_scrambling_stats.diff/PHY_vars_eNB->dlsch_scrambling_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_eNB->dlsch_scrambling_stats.trials); @@ -3240,7 +3304,9 @@ PHY_vars_UE->lte_ue_pdcch_vars[0]->num_pdcch_symbols, printf("|__ DLSCH sub-block interleaving time :%f us (%d trials)\n",((double)PHY_vars_eNB->dlsch_interleaving_stats.trials/PHY_vars_eNB->dlsch_encoding_stats.trials)*(double)PHY_vars_eNB->dlsch_interleaving_stats.diff/PHY_vars_eNB->dlsch_interleaving_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_eNB->dlsch_interleaving_stats.trials); printf("\n\nUE RX function statistics (per 1ms subframe)\n\n"); - printf("Total PHY proc rx :%f us (%d trials)\n",(double)PHY_vars_UE->phy_proc_rx.diff/PHY_vars_UE->phy_proc_rx.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->phy_proc_rx.trials*2/3); + double std_phy_proc_rx = sqrt((double)PHY_vars_UE->phy_proc_rx.diff_square/pow(cpu_freq_GHz,2)/pow(1000,2)/PHY_vars_UE->phy_proc_rx.trials - pow((double)PHY_vars_UE->phy_proc_rx.diff/PHY_vars_UE->phy_proc_rx.trials/cpu_freq_GHz/1000,2)); + printf("Total PHY proc rx :%f us (%d trials)\n",(double)PHY_vars_UE->phy_proc_rx.diff/PHY_vars_UE->phy_proc_rx.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->phy_proc_rx.trials*2/3); + printf("|__Statistcs std: %fus max: %fus min: %fus median %fus q1 %fus q3 %fus n_dropped: %d packet \n", std_phy_proc_rx, t_rx_max, t_rx_min, rx_median, rx_q1, rx_q3, n_rx_dropped); printf("DLSCH OFDM demodulation and channel_estimation time :%f us (%d trials)\n",(nsymb)*(double)PHY_vars_UE->ofdm_demod_stats.diff/PHY_vars_UE->ofdm_demod_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->ofdm_demod_stats.trials*2/3); printf("|__ DLSCH rx dft :%f us (%d trials)\n",(nsymb*PHY_vars_UE->lte_frame_parms.nb_antennas_rx)*(double)PHY_vars_UE->rx_dft_stats.diff/PHY_vars_UE->rx_dft_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->rx_dft_stats.trials*2/3); printf("|__ DLSCH channel estimation time :%f us (%d trials)\n",(4.0)*(double)PHY_vars_UE->dlsch_channel_estimation_stats.diff/PHY_vars_UE->dlsch_channel_estimation_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->dlsch_channel_estimation_stats.trials*2/3); diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c index 19b5b37162bbbd43c1a0f64f6138ea75326574a6..3366c907e0f56d333a1e9e09c0defee127d177b7 100644 --- a/openair1/SIMULATION/LTE_PHY/ulsim.c +++ b/openair1/SIMULATION/LTE_PHY/ulsim.c @@ -30,7 +30,7 @@ /*! \file ulsim.c \brief Top-level DL simulator \author R. Knopp - \date 2011 + \date 2011 - 2014 \version 0.1 \company Eurecom \email: knopp@eurecom.fr @@ -87,11 +87,20 @@ extern uint16_t beta_ack[16],beta_ri[16],beta_cqi[16]; //extern char* namepointer_chMag ; + #ifdef XFORMS FD_lte_phy_scope_enb *form_enb; char title[255]; #endif +/*the following parameters are used to control the processing times*/ +double t_tx_max = -1000000000; /*!< \brief initial max process time for tx */ +double t_rx_max = -1000000000; /*!< \brief initial max process time for rx */ +double t_tx_min = 1000000000; /*!< \brief initial min process time for tx */ +double t_rx_min = 1000000000; /*!< \brief initial min process time for tx */ +int n_tx_dropped = 0; /*!< \brief initial max process time for tx */ +int n_rx_dropped = 0; /*!< \brief initial max process time for rx */ + void lte_param_init(unsigned char N_tx, unsigned char N_rx,unsigned char transmission_mode,uint8_t extended_prefix_flag,uint8_t N_RB_DL,uint8_t frame_type,uint8_t tdd_config,uint8_t osf) { LTE_DL_FRAME_PARMS *lte_frame_parms; @@ -895,6 +904,12 @@ int main(int argc, char **argv) { reset_meas(&PHY_vars_eNB->ulsch_tc_intl1_stats); reset_meas(&PHY_vars_eNB->ulsch_tc_intl2_stats); + // initialization + struct list time_vector_tx; + initialize(&time_vector_tx); + struct list time_vector_rx; + initialize(&time_vector_rx); + for (trials = 0;trials<n_frames;trials++) { // printf("*"); // PHY_vars_UE->frame++; @@ -1270,8 +1285,53 @@ int main(int argc, char **argv) { #ifdef XFORMS phy_scope_eNB(form_enb,PHY_vars_eNB,0); #endif + /*calculate the total processing time for each packet, get the max, min, and number of packets that exceed t>3000us*/ + double t_tx = (double)PHY_vars_UE->phy_proc_tx.p_time/cpu_freq_GHz/1000.0; + double t_rx = (double)PHY_vars_eNB->phy_proc_rx.p_time/cpu_freq_GHz/1000.0; + if (t_tx > t_tx_max) + t_tx_max = t_tx; + if (t_tx < t_tx_min) + t_tx_min = t_tx; + if (t_rx > t_rx_max) + t_rx_max = t_rx; + if (t_rx < t_rx_min) + t_rx_min = t_rx; + if (t_tx > 2000) + n_tx_dropped++; + if (t_rx > 2000) + n_rx_dropped++; + + push_front(&time_vector_tx, t_tx); + push_front(&time_vector_rx, t_rx); } //trials + double table_tx[time_vector_tx.size]; + totable(table_tx, &time_vector_tx); + double table_rx[time_vector_rx.size]; + totable(table_rx, &time_vector_rx); + + // sort table + qsort (table_tx, time_vector_tx.size, sizeof(double), &compare); + qsort (table_rx, time_vector_rx.size, sizeof(double), &compare); +#ifdef DEBUG + int n; + printf("The transmitter raw data: \n"); + for (n=0; n< time_vector_tx.size; n++) + printf("%f ", table_tx[n]); + printf("\n"); + printf("The receiver raw data: \n"); + for (n=0; n< time_vector_rx.size; n++) + printf("%f ", table_rx[n]); + printf("\n"); +#endif + double tx_median = table_tx[time_vector_tx.size/2]; + double tx_q1 = table_tx[time_vector_tx.size/4]; + double tx_q3 = table_tx[3*time_vector_tx.size/4]; + + double rx_median = table_rx[time_vector_rx.size/2]; + double rx_q1 = table_rx[time_vector_rx.size/4]; + double rx_q3 = table_rx[3*time_vector_rx.size/4]; + printf("\n**********rb: %d ***mcs : %d *********SNR = %f dB (%f): TX %d dB (gain %f dB), N0W %f dB, I0 %d dB, delta_IF %d [ (%d,%d) dB / (%d,%d) dB ]**************************\n", nb_rb,mcs,SNR,SNR2, tx_lev_dB, @@ -1334,7 +1394,9 @@ int main(int argc, char **argv) { if (dump_perf==1) { printf("UE TX function statistics (per 1ms subframe)\n\n"); + double std_phy_proc_tx = sqrt((double)PHY_vars_UE->phy_proc_tx.diff_square/pow(cpu_freq_GHz,2)/pow(1000,2)/PHY_vars_UE->phy_proc_tx.trials - pow((double)PHY_vars_UE->phy_proc_tx.diff/PHY_vars_UE->phy_proc_tx.trials/cpu_freq_GHz/1000,2)); printf("Total PHY proc tx :%f us (%d trials)\n",(double)PHY_vars_UE->phy_proc_tx.diff/PHY_vars_UE->phy_proc_tx.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->phy_proc_tx.trials); + printf("|__ Statistics std: %f us max: %fus min: %fus median %fus q1 %fus q3 %fus n_dropped: %d packet \n",std_phy_proc_tx, t_tx_max, t_tx_min, tx_median, tx_q1, tx_q3, n_tx_dropped); printf("OFDM_mod time :%f us (%d trials)\n",(double)PHY_vars_UE->ofdm_mod_stats.diff/PHY_vars_UE->ofdm_mod_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->ofdm_mod_stats.trials); printf("ULSCH modulation time :%f us (%d trials)\n",(double)PHY_vars_UE->ulsch_modulation_stats.diff/PHY_vars_UE->ulsch_modulation_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->ulsch_modulation_stats.trials); printf("ULSCH encoding time :%f us (%d trials)\n",(double)PHY_vars_UE->ulsch_encoding_stats.diff/PHY_vars_UE->ulsch_encoding_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->ulsch_encoding_stats.trials); @@ -1345,8 +1407,12 @@ int main(int argc, char **argv) { printf("|__ ULSCH multiplexing time :%f us (%d trials)\n",((double)PHY_vars_UE->ulsch_multiplexing_stats.trials/PHY_vars_UE->ulsch_encoding_stats.trials)*(double)PHY_vars_UE->ulsch_multiplexing_stats.diff/PHY_vars_UE->ulsch_multiplexing_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->ulsch_multiplexing_stats.trials); printf("\n\neNB RX function statistics (per 1ms subframe)\n\n"); - printf("Total PHY proc rx :%f us (%d trials)\n",(double)PHY_vars_eNB->phy_proc_rx.diff/PHY_vars_eNB->phy_proc_rx.trials/cpu_freq_GHz/1000.0,PHY_vars_eNB->phy_proc_rx.trials); + double std_phy_proc_rx = sqrt((double)PHY_vars_eNB->phy_proc_rx.diff_square/pow(cpu_freq_GHz,2)/pow(1000,2)/PHY_vars_eNB->phy_proc_rx.trials - pow((double)PHY_vars_eNB->phy_proc_rx.diff/PHY_vars_eNB->phy_proc_rx.trials/cpu_freq_GHz/1000,2)); + printf("Total PHY proc rx :%f us (%d trials)\n",(double)PHY_vars_eNB->phy_proc_rx.diff/PHY_vars_eNB->phy_proc_rx.trials/cpu_freq_GHz/1000.0,PHY_vars_eNB->phy_proc_rx.trials); + printf("|__ Statistcs std: %fus max: %fus min: %fus median %fus q1 %fus q3 %fus n_dropped: %d packet \n", std_phy_proc_rx, t_rx_max, t_rx_min, rx_median, rx_q1, rx_q3, n_rx_dropped); + printf("OFDM_demod time :%f us (%d trials)\n",(double)PHY_vars_eNB->ofdm_demod_stats.diff/PHY_vars_eNB->ofdm_demod_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_eNB->ofdm_demod_stats.trials); + printf("ULSCH demodulation time :%f us (%d trials)\n",(double)PHY_vars_eNB->ulsch_demodulation_stats.diff/PHY_vars_eNB->ulsch_demodulation_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_eNB->ulsch_demodulation_stats.trials); printf("ULSCH Decoding time (%.2f Mbit/s, avg iter %f) :%f us (%d trials, max %f)\n", PHY_vars_UE->ulsch_ue[0]->harq_processes[harq_pid]->TBS/1000.0,(double)avg_iter/iter_trials, diff --git a/openair2/UTIL/LISTS/list.c b/openair2/UTIL/LISTS/list.c index e45478e07fdae706125cff10b02af4e539f8ac3e..44310192084c1c244311e0e4986e50365657c036 100755 --- a/openair2/UTIL/LISTS/list.c +++ b/openair2/UTIL/LISTS/list.c @@ -1,20 +1,39 @@ +/******************************************************************************* + OpenAirInterface + Copyright(c) 1999 - 2014 Eurecom -/*! \file pad_list.c -* \brief list management primimtives -* \author Mohamed Said MOSLI BOUKSIAA, Lionel GAUTHIER, Navid Nikaein + OpenAirInterface 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 3 of the License, or + (at your option) any later version. + + + OpenAirInterface 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 OpenAirInterface.The full GNU General Public License is + included in this distribution in the file called "COPYING". If not, + see <http://www.gnu.org/licenses/>. + + Contact Information + OpenAirInterface Admin: openair_admin@eurecom.fr + OpenAirInterface Tech : openair_tech@eurecom.fr + OpenAirInterface Dev : openair4g-devel@eurecom.fr + + Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE + + *******************************************************************************/ +/*! \file list.c +* \brief list management primimtives. It includes three implementations: (1) with mem_blocks, (2) standard list implementation (mem usage 314MB) (3) Linux Queue-based implementation (mem usage 394 MB) +* \author Navid Nikaein, Mohamed Said MOSLI BOUKSIAA, Lionel GAUTHIER * \date 2012 - 2014 * \version 0.5 * @ingroup util */ -/*************************************************************************** - list_t.c - description - ------------------- - ------------------- - AUTHOR : Lionel GAUTHIER - COMPANY : EURECOM - EMAIL : Lionel.Gauthier@eurecom.fr - ***************************************************************************/ #define LIST_C #define NULL 0 @@ -240,3 +259,165 @@ list_display (list_t * listP) //msg ("[SDU_MNGT][WARNING] display_cnt_list() : list is NULL\n"); } } +#ifndef LINUX_LIST +/*! \fn void push_front(struct list* z, double val) +* \brief this function pushes front new values in a predefined list. +* \param z is the predefined list +* val is the new value to be pushed inside the list +* \return +*/ +void +push_front(struct list* z, double val) { + + struct node* p = (struct node*) malloc(sizeof(struct node)); + + p->next = z->head; + p->val = val; + z->head = p; + + z->size++; + + return; + +} + +/*! \fn void initialize(struct list* z) +* \brief initialize a list structure. +* \param z is the list +* \return +*/ +void +initialize(struct list* z) { + z->head = NULL; + z->size = 0; + + return; +} + +/*! \fn void del(struct list* z) +* \brief delete a list structure. +* \param z is the list +* \return +*/ +void +del(struct list* z) { + struct node* cur; + struct node* x = z->head; + + while(x) { + cur = x; + x = x->next; + free(cur); + } + + z->head = NULL; + z->size = 0; + + return; +} +/*! \fn void totable(double* table, struct list* v) +* \brief convert a list structure to a table. +* \param table is a pointer to double table +* v is the list to be converted +* \return +*/ +void +totable(double* table, struct list* v) { + int i = 0; + + struct node* x = v->head; + + while(x) { + table[i] = x->val; + i++; + x = x->next; + } + + return; +} +/*! \fn int compare (const void * a, const void * b) +* \brief compare the value of two parameters +* \param a is a double, b is another double +* \return 1 if a>b, -0 if a<b +*/ +int compare (const void * a, const void * b) +{ + double x = *(double*)a; + double y = *(double*)b; + + return ( x > y ); +} +#else +// push an element to the head of the list +void push_front(struct list* z, double val) { + struct entry* p = (struct entry*) malloc(sizeof(struct entry)); + p->val = val; + + LIST_INSERT_HEAD(&z->head, p, entries); + z->size++; + + return; + +} + + +// initialization +void initialize(struct list* z) { + LIST_INIT(&z->head); + z->size = 0; + + return; +} + +// delete +void del(struct list* z) { + while (z->head.lh_first != NULL) { + free(z->head.lh_first); + LIST_REMOVE(z->head.lh_first, entries); + } + z->size = 0; + + return; +} + +// convert the list to a table +void totable(double* table, struct list* v) { + int i = 0; + + struct entry* x; + + for (x = v->head.lh_first; x != NULL; x = x->entries.le_next) { + table[i] = x->val; + i++; + } + + return; +} + +int compare (const void * a, const void * b) +{ + double x = *(double*)a; + double y = *(double*)b; + + return ( x > y ); +} +#endif + +/*! \fn int32_t calculate_median(struct list *loc_list) +* \brief calculate the median of a list +* \param loc_list is the list +* \return the median value +*/ +int32_t calculate_median(struct list *loc_list) { + int32_t median = 0; + double* table = (double*) malloc(loc_list->size * sizeof(double)); + totable(table, loc_list); + /// sort the table in ascending way + qsort (table, loc_list->size, sizeof(double), &compare); + /// median is the value at middle the sorted table + /// Q1 is the value at 1/4 the sorted table + /// Q3 is the value at 3/4 the sorted table + median = table[loc_list->size/2]; + free(table); + return median; +} diff --git a/openair2/UTIL/LISTS/list.h b/openair2/UTIL/LISTS/list.h index 36db0e0483baf0818f25406def5a2f30c71bc7b6..1c53af2bb8604b35978601a020c601be445cb26d 100755 --- a/openair2/UTIL/LISTS/list.h +++ b/openair2/UTIL/LISTS/list.h @@ -36,6 +36,9 @@ # endif //----------------------------------------------------------------------------- #include "platform_constants.h" +#include<linux/types.h> +#include<stdlib.h> +#include<sys/queue.h> #define LIST_NAME_MAX_CHAR 32 @@ -75,5 +78,38 @@ public_list2( void list2_add_head (mem_block_t* , list2_t* );) public_list2( void list2_add_tail (mem_block_t* , list2_t* );) public_list2( void list2_add_list (list2_t* , list2_t* );) public_list2( void list2_display (list2_t* );) +//----------------------------------------------------------------------------- +/* The following lists are used for sorting numbers */ +#ifndef LINUX_LIST +/*! \brief the node structure */ +struct node { + struct node* next; /*!< \brief is a node pointer */ + double val; /*!< \brief is a the value of a node pointer*/ +}; +//----------------------------------------------------------------------------- +/*! \brief the list structure */ +struct list { + struct node* head; /*!< \brief is a node pointer */ + ssize_t size; /*!< \brief is the list size*/ +}; +#else +//----------------------------------------------------------------------------- +struct entry { + double val; + LIST_ENTRY(entry) entries; +}; +//----------------------------------------------------------------------------- +struct list { + LIST_HEAD(listhead, entry) head; + ssize_t size; +}; +#endif +//----------------------------------------------------------------------------- +public_list2( void push_front (struct list*, double); ) +public_list2( void initialize (struct list*); ) +public_list2( void del (struct list*); ) +public_list2( void totable (double*, struct list*);) +public_list2( int compare (const void * a, const void * b);) +public_list2( int32_t calculate_median(struct list *loc_list);) #endif