📄 simlib.c
字号:
/* This is simlib.c (adapted from SUPERSIMLIB, written by Gregory Glockner). */
/* Include files. */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "simlibdefs.h"
/* Declare simlib global variables. */
int *list_rank, *list_size, next_event_type, maxatr = 0, maxlist = 0;
float *transfer, sim_time, prob_distrib[26];
struct master {
float *value;
struct master *pr;
struct master *sr;
} **head, **tail;
/* Declare simlib functions. */
void init_simlib(void);
void list_file(int option, int list);
void list_remove(int option, int list);
void timing(void);
void event_schedule(float time_of_event, int type_of_event);
int event_cancel(int event_type);
float sampst(float value, int variable);
float timest(float value, int variable);
float filest(int list);
void out_sampst(FILE *unit, int lowvar, int highvar);
void out_timest(FILE *unit, int lowvar, int highvar);
void out_filest(FILE *unit, int lowlist, int highlist);
void pprint_out(FILE *unit, int i);
float expon(float mean, int stream);
int random_integer(float prob_distrib[], int stream);
float uniform(float a, float b, int stream);
float erlang(int m, float mean, int stream);
float lcgrand(int stream);
void lcgrandst(long zset, int stream);
long lcgrandgt(int stream);
void init_simlib()
{
/* Initialize simlib.c. List LIST_EVENT is reserved for event list, ordered by
event time. init_simlib must be called from main by user. */
int list, listsize;
if (maxlist < 1) maxlist = MAX_LIST;
listsize = maxlist + 1;
/* Initialize system attributes. */
sim_time = 0.0;
if (maxatr < 4) maxatr = MAX_ATTR;
/* Allocate space for the lists. */
list_rank = (int *) calloc(listsize, sizeof(int));
list_size = (int *) calloc(listsize, sizeof(int));
head = (struct master **) calloc(listsize, sizeof(struct master *));
tail = (struct master **) calloc(listsize, sizeof(struct master *));
transfer = (float *) calloc(maxatr + 1, sizeof(float));
/* Initialize list attributes. */
for(list = 1; list <= maxlist; ++list) {
head [list] = NULL;
tail [list] = NULL;
list_size[list] = 0;
list_rank[list] = 0;
}
/* Set event list to be ordered by event time. */
list_rank[LIST_EVENT] = EVENT_TIME;
/* Initialize statistical routines. */
sampst(0.0, 0);
timest(0.0, 0);
}
void list_file(int option, int list)
{
/* Place transfr into list "list".
Update timest statistics for the list.
option = FIRST place at start of list
LAST place at end of list
INCREASING place in increasing order on attribute list_rank(list)
DECREASING place in decreasing order on attribute list_rank(list)
(ties resolved by FIFO) */
struct master *row, *ahead, *behind, *ihead, *itail;
int item, postest;
////////////////////////////////////////////////////////////////////////////////
/* This section is added by Bowlderforest at 2nd.March,2004. The aim is
to keep the new transfer[] as same as the old one when it is created
by the calloc() function. */
float* t_transfer;
int i;
////////////////////////////////////////////////////////////////////////////////
/* If the list value is improper, stop the simulation. */
if(!((list >= 0) && (list <= MAX_LIST))) {
printf("\nInvalid list %d for list_file at time %f\n", list, sim_time);
exit(1);
}
/* Increment the list size. */
list_size[list]++;
/* If the option value is improper, stop the simulation. */
if(!((option >= 1) && (option <= DECREASING))) {
printf(
"\n%d is an invalid option for list_file on list %d at time %f\n",
option, list, sim_time);
exit(1);
}
/* If this is the first record in this list, just make space for it. */
if(list_size[list] == 1) {
row = (struct master *) malloc(sizeof(struct master));
head[list] = row ;
tail[list] = row ;
(*row).pr = NULL;
(*row).sr = NULL;
}
else { /* There are other records in the list. */
/* Check the value of option. */
if ((option == INCREASING) || (option == DECREASING)) {
item = list_rank[list];
if(!((item >= 1) && (item <= maxatr))) {
printf(
"%d is an improper value for rank of list %d at time %f\n",
item, list, sim_time) ;
exit(1);
}
row = head[list];
behind = NULL; /* Dummy value for the first iteration. */
/* Search for the correct location. */
if (option == INCREASING) {
postest = (transfer[item] >= (*row).value[item]);
while (postest) {
behind = row;
row = (*row).sr;
postest = (behind != tail[list]);
if (postest)
postest = (transfer[item] >= (*row).value[item]);
}
}
else {
postest = (transfer[item] <= (*row).value[item]);
while (postest) {
behind = row;
row = (*row).sr;
postest = (behind != tail[list]);
if (postest)
postest = (transfer[item] <= (*row).value[item]);
}
}
/* Check to see if position is first or last. If so, take care of
it below. */
if (row == head[list])
option = FIRST;
else
if (behind == tail[list])
option = LAST;
else { /* Insert between preceding and succeeding records. */
ahead = (*behind).sr;
row = (struct master *)
malloc(sizeof(struct master));
(*row).pr = behind;
(*behind).sr = row;
(*ahead).pr = row;
(*row).sr = ahead;
}
} /* End if inserting in increasing or decreasing order. */
if (option == FIRST) {
row = (struct master *) malloc(sizeof(struct master));
ihead = head[list];
(*ihead).pr = row;
(*row).sr = ihead;
(*row).pr = NULL;
head[list] = row;
}
if (option == LAST) {
row = (struct master *) malloc(sizeof(struct master));
itail = tail[list];
(*row).pr = itail;
(*itail).sr = row;
(*row).sr = NULL;
tail[list] = row;
}
}
/* Copy the data. */
(*row).value = transfer;
/* Make room for new transfer. */
transfer = (float *) calloc(maxatr + 1, sizeof(float));
////////////////////////////////////////////////////////////////////////////////
/* This section is added by Bowlderforest at 2nd.March,2004. The aim is
to keep the new transfer[] as same as the old one when it is created
by the calloc() function. */
t_transfer = (*row).value;
for(i = 1; i <= maxatr; i++) transfer[i] = t_transfer[i];
////////////////////////////////////////////////////////////////////////////////
/* Update the area under the number-in-list curve. */
timest((float)list_size[list], TIM_VAR + list);
}
void list_remove(int option, int list)
{
/* Remove a record from list "list" and copy attributes into transfer.
Update timest statistics for the list.
option = FIRST remove first record in the list
LAST remove last record in the list */
struct master *row, *ihead, *itail;
/* If the list value is improper, stop the simulation. */
if(!((list >= 0) && (list <= MAX_LIST))) {
printf("\nInvalid list %d for list_remove at time %f\n",
list, sim_time);
exit(1);
}
/* If the list is empty, stop the simulation. */
if(list_size[list] <= 0) {
printf("\nUnderflow of list %d at time %f\n", list, sim_time);
exit(1);
}
/* Decrement the list size. */
list_size[list]--;
/* If the option value is improper, stop the simulation. */
if(!(option == FIRST || option == LAST)) {
printf(
"\n%d is an invalid option for list_remove on list %d at time %f\n",
option, list, sim_time);
exit(1);
}
if(list_size[list] == 0) {
/* There is only 1 record, so remove it. */
row = head[list];
head[list] = NULL;
tail[list] = NULL;
}
else {
/* There is more than 1 record, so remove according to the desired
option. */
switch(option) {
/* Remove the first record in the list. */
case FIRST:
row = head[list];
ihead = (*row).sr;
(*ihead).pr = NULL;
head[list] = ihead;
break;
/* Remove the last record in the list. */
case LAST:
row = tail[list];
itail = (*row).pr;
(*itail).sr = NULL;
tail[list] = itail;
break;
}
}
/* Copy the data and free memory. */
free((char *)transfer);
transfer = (*row).value;
free((char *)row);
/* Update the area under the number-in-list curve. */
timest((float)list_size[list], TIM_VAR + list);
}
void timing()
{
/* Remove next event from event list, placing its attributes in transfer.
Set sim_time (simulation time) to event time, transfer[1].
Set next_event_type to this event type, transfer[2]. */
/* Remove the first event from the event list and put it in transfer[]. */
list_remove(FIRST, LIST_EVENT);
/* Check for a time reversal. */
if(transfer[EVENT_TIME] < sim_time) {
printf(
"\nAttempt to schedule event type %f for time %f at time %f\n",
transfer[EVENT_TYPE], transfer[EVENT_TIME], sim_time);
exit(1);
}
/* Advance the simulation clock and set the next event type. */
sim_time = transfer[EVENT_TIME];
next_event_type = transfer[EVENT_TYPE];
}
void event_schedule(float time_of_event, int type_of_event)
{
/* Schedule an event at time event_time of type event_type. If attributes
beyond the first two (reserved for the event time and the event type) are
being used in the event list, it is the user's responsibility to place their
values into the transfer array before invoking event_schedule. */
transfer[EVENT_TIME] = time_of_event;
transfer[EVENT_TYPE] = type_of_event;
list_file(INCREASING, LIST_EVENT);
}
int event_cancel(int event_type)
{
/* Remove the first event of type event_type from the event list, leaving its
attributes in transfer. If something is cancelled, event_cancel returns 1;
if no match is found, event_cancel returns 0. */
struct master *row, *ahead, *behind;
static float high, low, value;
/* If the event list is empty, do nothing and return 0. */
if(list_size[LIST_EVENT] == 0) return 0;
/* Search the event list. */
row = head[LIST_EVENT];
low = event_type - EPSILON;
high = event_type + EPSILON;
value = (*row).value[EVENT_TYPE] ;
while (((value <= low) || (value >= high)) && (row != tail[LIST_EVENT])) {
row = (*row).sr;
value = (*row).value[EVENT_TYPE];
}
/* Check to see if this is the end of the event list. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -