home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume6 / gspn < prev    next >
Text File  |  1989-04-30  |  83KB  |  3,018 lines

  1. Newsgroups: comp.sources.misc
  2. From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  3. Subject: v06i094: Petri Net Simulator
  4. Keywords: Generalize Stochastic Petri Nets, performance analysis
  5. Organization: Carnegie-Mellon University, CS/RI
  6. Reply-To: agn@unh.cs.cmu.edu (Andreas Nowatzyk)
  7.  
  8. Posting-number: Volume 6, Issue 94
  9. Submitted-by: agn@unh.cs.cmu.edu (Andreas Nowatzyk)
  10. Archive-name: gspn
  11.  
  12. This code simulates timed generalized stochastic Petri nets
  13. (GSPNs) that can be used to analyze the performance of parallel
  14. systems (both hardware and software). An overview on how to
  15. use GSPN can be found in "Performance Analysis Using Stochastic
  16. Petri Nets", by Michael K. Molloy, IEEE Transactions on Computers,
  17. Vol. C-31, #9, Sept. 1982.
  18.  
  19. The GSPN Simulator (GS) below accepts a symbolic description of a
  20. GSPN and a set of performance expressions. GS simulates the network
  21. and evaluates the given performance expressions. After execution,
  22. the results are printed with an estimate of the expected simulation
  23. error.
  24.  
  25. In addition to the symbolic network description (which can be prepared
  26. with any text editor) an interface to the 'GreatSPN' GSPN package
  27. by G. Chiola is provided, which has a nice graphical network editor.
  28. GreatSPN is not PD code and GS does not contain any code from GreatSPN.
  29.  
  30. M---------------------- Cut here --------------------------
  31. #
  32. # type    sh /usru1/agn/gspn/../gs.shar   to unpack this archive.
  33. #
  34. echo extracting def2n.l...
  35. cat >def2n.l <<'!E!O!F!'
  36. /************************************************************************\
  37. *                                                                        *
  38. *  GS: A Generalized, stochastic petri net Simulator                     *
  39. *      V0.01      March 1989      Andreas Nowatzyk (agn@unh.cs.cmu.edu)  *
  40. *      Carnegie-Mellon Univerity, School of Computer Science             *
  41. *      Schenley Park, Pittsburgh, PA 15213                               *
  42. *                                                                        *
  43. \************************************************************************/
  44.  
  45. %%
  46.  
  47. [^%]*"%"            ; /* skip header */
  48.  
  49. "|".*":"            {int i; for (i = 1; i < yyleng; i++)
  50.                             if (yytext[i] == ' ') {yytext[i] = 0; break;}
  51.                  printf ("RESULT %s :", yytext + 1);}
  52.  
  53. (p|P)[ /t/n]*"{"         printf ("Prob{");
  54. (e|E)[ /t/n]*"{"         printf ("Expt{");
  55.  
  56. "&"                 printf ("&&");
  57. "="                 printf ("==");
  58. "/="                 printf ("!=");
  59. "~"                 printf ("!");
  60. o/[ /n/t(~#]             printf ("||");        /* that was real stupid to use an 'o' for OR */
  61.  
  62. ^"|"$                 ; /* ignore EOF */
  63.  
  64. %%
  65. !E!O!F!
  66. #
  67. # type    sh /usru1/agn/gspn/../gs.shar   to unpack this archive.
  68. #
  69. echo extracting example.n...
  70. cat >example.n <<'!E!O!F!'
  71. /* variable load, 8x8 register file, async, fixed sized packets */
  72.  
  73. RESULT Throughput : 0.125 Prob{#O1b > 0} + 0.125 Prob{#O2b > 0} +
  74.             0.125 Prob{#O3b > 0} + 0.125 Prob{#O4b > 0} +
  75.             0.125 Prob{#O5b > 0} + 0.125 Prob{#O6b > 0} +
  76.             0.125 Prob{#O7b > 0} + 0.125 Prob{#O8b > 0}  ;
  77.  
  78. RESULT Latency :    Dwell{Input} +
  79.             0.125 Dwell{O1} + 0.125 Dwell{O2} + 0.125 Dwell{O3} + 0.125 Dwell{O4} +
  80.             0.125 Dwell{O5} + 0.125 Dwell{O6} + 0.125 Dwell{O7} + 0.125 Dwell{O8}  ;
  81.  
  82. PARAM buff 8;
  83. PARAM load 1.0;
  84.  
  85. PLACE Output #marks= 0;
  86. PLACE Input #marks= 0;
  87. PLACE Idle #marks= buff;
  88. PLACE P28 #marks= 0;
  89.  
  90. PLACE O1 #marks= 0;
  91. PLACE O1b #marks= 0;
  92. PLACE O1i #marks= 0;
  93.  
  94. PLACE O2 #marks= 0;
  95. PLACE O2b #marks= 0;
  96. PLACE O2i #marks= 0;
  97.  
  98. PLACE O3 #marks= 0;
  99. PLACE O3b #marks= 0;
  100. PLACE O3i #marks= 0;
  101.  
  102. PLACE O4 #marks= 0;
  103. PLACE O4b #marks= 0;
  104. PLACE O4i #marks= 0;
  105.  
  106. PLACE O5 #marks= 0;
  107. PLACE O5b #marks= 0;
  108. PLACE O5i #marks= 0;
  109.  
  110. PLACE O6 #marks= 0;
  111. PLACE O6b #marks= 0;
  112. PLACE O6i #marks= 0;
  113.  
  114. PLACE O7 #marks= 0;
  115. PLACE O7b #marks= 0;
  116. PLACE O7i #marks= 0;
  117.  
  118. PLACE O8 #marks= 0;
  119. PLACE O8b #marks= 0;
  120. PLACE O8i #marks= 0;
  121.  
  122. PLACE Q1 #marks= 1;
  123. PLACE Q2 #marks= 1;
  124. PLACE Q3 #marks= 1;
  125. PLACE Q4 #marks= 1;
  126. PLACE Q5 #marks= 1;
  127. PLACE Q6 #marks= 1;
  128. PLACE Q7 #marks= 1;
  129. PLACE Q8 #marks= 1;
  130.  
  131. TRANS source exp rate=load : --> Input;
  132. TRANS enter imm : Input Idle --> P28;
  133. TRANS drain imm : Output --> ;
  134.  
  135. TRANS x8 det rate= 1.000000e+00, dep= 1 : O8b --> O8i;
  136. TRANS x7 det rate= 1.000000e+00, dep= 1 : O7b --> O7i;
  137. TRANS x6 det rate= 1.000000e+00, dep= 1 : O6b --> O6i;
  138. TRANS x5 det rate= 1.000000e+00, dep= 1 : O5b --> O5i;
  139. TRANS x4 det rate= 1.000000e+00, dep= 1 : O4b --> O4i;
  140. TRANS x3 det rate= 1.000000e+00, dep= 1 : O3b --> O3i;
  141. TRANS x2 det rate= 1.000000e+00, dep= 1 : O2b --> O2i;
  142. TRANS x1 det rate= 1.000000e+00, dep= 1 : O1b --> O1i;
  143.  
  144. TRANS q1 normal rate= 1.000000e+00, dep= 1 : Q1 --> O1i;
  145. TRANS q2 normal rate= 1.000000e+00, dep= 1 : Q2 --> O2i;
  146. TRANS q3 normal rate= 1.000000e+00, dep= 1 : Q3 --> O3i;
  147. TRANS q4 normal rate= 1.000000e+00, dep= 1 : Q4 --> O4i;
  148. TRANS q5 normal rate= 1.000000e+00, dep= 1 : Q5 --> O5i;
  149. TRANS q6 normal rate= 1.000000e+00, dep= 1 : Q6 --> O6i;
  150. TRANS q7 normal rate= 1.000000e+00, dep= 1 : Q7 --> O7i;
  151. TRANS q8 normal rate= 1.000000e+00, dep= 1 : Q8 --> O8i;
  152.  
  153. TRANS s1 imm rate= 1.000000e+00, dep= 1 : P28 --> O1;
  154. TRANS s2 imm rate= 1.000000e+00, dep= 1 : P28 --> O2;
  155. TRANS s3 imm rate= 1.000000e+00, dep= 1 : P28 --> O3;
  156. TRANS s4 imm rate= 1.000000e+00, dep= 1 : P28 --> O4;
  157. TRANS s5 imm rate= 1.000000e+00, dep= 1 : P28 --> O5;
  158. TRANS s6 imm rate= 1.000000e+00, dep= 1 : P28 --> O6;
  159. TRANS s7 imm rate= 1.000000e+00, dep= 1 : P28 --> O7;
  160. TRANS s8 imm rate= 1.000000e+00, dep= 1 : P28 --> O8;
  161.  
  162. TRANS o1 imm rate= 1.000000e+00, dep= 1 : O1i O1 --> O1b Output Idle;
  163. TRANS o2 imm rate= 1.000000e+00, dep= 1 : O2i O2 --> O2b Output Idle;
  164. TRANS o3 imm rate= 1.000000e+00, dep= 1 : O3i O3 --> O3b Output Idle;
  165. TRANS o4 imm rate= 1.000000e+00, dep= 1 : O4i O4 --> O4b Output Idle;
  166. TRANS o5 imm rate= 1.000000e+00, dep= 1 : O5i O5 --> O5b Output Idle;
  167. TRANS o6 imm rate= 1.000000e+00, dep= 1 : O6i O6 --> O6b Output Idle;
  168. TRANS o7 imm rate= 1.000000e+00, dep= 1 : O7i O7 --> O7b Output Idle;
  169. TRANS o8 imm rate= 1.000000e+00, dep= 1 : O8i O8 --> O8b Output Idle;
  170. #end
  171. !E!O!F!
  172. #
  173. # type    sh /usru1/agn/gspn/../gs.shar   to unpack this archive.
  174. #
  175. echo extracting gs.1...
  176. cat >gs.1 <<'!E!O!F!'
  177. .TH GS 1 4/14/89
  178. .CM 4
  179. .SH NAME
  180. gs \- Generalized Stochastic Petri-Net Simulator
  181. .SH SYNOPSIS
  182. mk_sim [net description file]
  183. .SH DESCRIPTION
  184. GS is a collection of programs and shell-scripts to generate fast
  185. Generalized Stochastic Petri-Net (GSPN) Simulators. GS is closely
  186. related to Giovanni Chiola's GreatSPN package, but can be used
  187. independently.
  188.  
  189. mk_sim is a shell script that will produce an executable simulator
  190. from a network description. If the sole argument to mk_sim is a file
  191. name ending in ".n", that file is assumed to contain the symbolic
  192. description of a GSPN. Otherwise, mk_sim is assuming that the argument
  193. is a GreatSPN network name and tries to convert the corresponding
  194. *.net and *.def files into an symbolic description file first.
  195.  
  196. The network description is converted into a C-data structure which is
  197. subsequently compiled with a generic set of simulator routines into
  198. an executable simulator.
  199.  
  200. Option switches supported by the simulator:
  201. .TP 
  202. -a <n>
  203. Alternative transition delay for bimodally timed transition
  204. as a fraction of the nominal delay.
  205. .br
  206. .ns
  207. .TP 
  208. -b <n>
  209. Percentage of times a bimodally timed transition will use the
  210. alternative delay: 0=never to 100=always
  211. .br
  212. .ns
  213. .TP 
  214. -v,c,o
  215. Verbose, comment and output file options are not really supported yet.
  216. (there is always something left to do)
  217. .br
  218. .ns
  219. .TP 
  220. -r <n>
  221. # of generations. The network is reset to its initial state
  222. before each generation. Nets with transient characteristics
  223. will require more generations. The default is 5.
  224. .br
  225. .ns
  226. .TP 
  227. -s <n>
  228. Seed for the random number generator.
  229. .br
  230. .ns
  231. .TP 
  232. -p <name> <value>
  233. Change a network parameter to the given value. Network parameters
  234. are specific to a particular net and are defined in the *.n file.
  235. .br
  236. .ns
  237. .TP 
  238. -f <n>
  239. .br
  240. # of transition firing per generation (default = 10000).
  241. .i0
  242. .DT
  243. .PP
  244. .SH "NET-FILE FORMAT"
  245. The original GreatSPN files (*.net and *.def files) are combined and converted
  246. into a more readable description of the GSPN (*.n files).
  247. This symbolic description
  248. is subsequently processed with cpp (the C-language preprocessor) to allow the
  249. use of macros and conditional compilation or to include libraries of sub-nets.
  250.  
  251. *.n files are an unordered sequence of statements plus optional comments and/or
  252. cpp-directives.
  253. The file is terminated by a "#end" - line.
  254.  
  255. 4 types of statements are supported, starting with the keywords PLACE, TRANS, PARAM
  256. and RESULT.
  257. Each statement is terminated with a ";".
  258.  
  259. PLACE statements define places of the network and the number of initial tokens.
  260.  
  261. TRANS statements define transitions.
  262. GS supports deterministic (det), immediate (imm),
  263. exponentially (exp), normally (normal) and bimodally (bimodal) timed transitions.
  264. The last 2 types are not supported by the GreatSPN package.
  265.  
  266. PARAM statements define a parameter with a defaults value that can be used instead
  267. of a numeric value for marking and transition rate specification.
  268. Parameters can
  269. be changed at run-time while numeric values are compiled into the code.
  270.  
  271. RESULT statements define performance expressions that are evaluated and reported.
  272. Expressions are composed out of 4 types of measures: Probabilities (Prob) report
  273. the fraction of time a logical expression in terms of places and token-numbers is
  274. true.
  275. Expected token numbers (Expt) report the number of tokens in a place and can be condition
  276. conditioned by a logic expression.
  277. Firing rates are available with the Fire keyword.
  278. Token dwell times are reported with the Dwell keyword.
  279. The last 2 items are extensions
  280. to GreatSPN.
  281. GS makes sure that expressions don't mix items with incompatible
  282. dimensions (such a probabilities and times).
  283.  
  284. Details of the file format can be deduced from the yacc-grammar or by inspection
  285. of examples.
  286. .SH FILES
  287. mk_sim:    shell script to assemble a simulator
  288. .br
  289. gs_pp:    preprocessor to build the simulator data structure
  290. .br
  291. net2n:    *.net to *.n file format converter
  292. .br
  293. def2n:    *.def to *.n file format converter
  294. .br
  295. GS.o:    generic simulator code (precompiled object)
  296. .br
  297. gs.h:    include file for final assembly
  298. .br
  299. gs.c:    compiles into network specific part
  300. .SH "SEE ALSO"
  301. GreatSPN User's Manual, Version 1.3, September 1987, Giovanni Chiola,
  302. Dipartimento di Informatica, Universia` degli Studi di Torino,
  303. corso Svizzera 185, 10149 Torino, Italy.
  304. .SH EXAMPLE
  305. "mk_sim foo" will create the simulator "foo" from "foo.net" and "foo.def".
  306. "foo.n" is also created, which contains the symbolic description of the
  307. network. Unlike "foo.net" and "foo.def", "foo.n" is almost human readable
  308. and can be changed with a normal text editor. "foo" can be created from
  309. "foo.n" with "mk_sim foo.n".
  310.  
  311. .SH BUGS
  312. GS does not support nets with multiserver transitions.
  313. The number of
  314. enabling dependencies is assumed to be one.
  315. This isn't hard to fix for
  316. immediate and exponential transitions, but deterministically timed
  317. transition would cause a substantial loss in speed.
  318.  
  319. Marking dependent transition rates are not supported (easily doable, but
  320. I have yet to figure out a use for it).
  321.  
  322. The number of firing per generation is left to the user.
  323. GreatSPN has a method
  324. to figure out a lower bound on this number, but it does not always come up
  325. with reasonable limits.
  326. Since GS is much faster, picking a conservative estimate
  327. appears easier.
  328. .SH HISTORY
  329. 14-Apr-89  Andreas Nowatzyk (agn) at Carnegie-Mellon University
  330. .br
  331.     Created Documentation (finally).
  332. !E!O!F!
  333. #
  334. # type    sh /usru1/agn/gspn/../gs.shar   to unpack this archive.
  335. #
  336. echo extracting gs.c...
  337. cat >gs.c <<'!E!O!F!'
  338. /************************************************************************\
  339. *                                                                        *
  340. *  GS: A Generalized, stochastic petri net Simulator                     *
  341. *      V0.01      March 1989      Andreas Nowatzyk (agn@unh.cs.cmu.edu)  *
  342. *      Carnegie-Mellon Univerity, School of Computer Science             *
  343. *      Schenley Park, Pittsburgh, PA 15213                               *
  344. *                                                                        *
  345. \************************************************************************/
  346.  
  347. /* GSPN simulator, main part:
  348.  *
  349.  * This module has only the net-specific componnets:
  350.  *    - the place-structures
  351.  *    - the transition structures
  352.  *    - the fire-functions
  353.  *    - all statically allocated storrage
  354.  *
  355.  */
  356.  
  357. #include <stdio.h>
  358. #define mainpgm
  359. #include "gs.h"
  360. #include "sim.h"
  361.  
  362. unsigned long n_places        = N_PLACES;        /* pass size info to other modules */
  363. unsigned long n_transitions = N_TRANSITIONS;
  364. unsigned long n_results        = N_RESULTS;
  365. unsigned long n_parameters  = N_PARAMETERS;
  366.  
  367. struct transition *TBUF[N_TRANSITIONS];
  368. !E!O!F!
  369. #
  370. # type    sh /usru1/agn/gspn/../gs.shar   to unpack this archive.
  371. #
  372. echo extracting gs.h...
  373. cat >gs.h <<'!E!O!F!'
  374. /************************************************************************\
  375. *                                                                        *
  376. *  GS: A Generalized, stochastic petri net Simulator                     *
  377. *      V0.01      March 1989      Andreas Nowatzyk (agn@unh.cs.cmu.edu)  *
  378. *      Carnegie-Mellon Univerity, School of Computer Science             *
  379. *      Schenley Park, Pittsburgh, PA 15213                               *
  380. *                                                                        *
  381. \************************************************************************/
  382.  
  383. /*
  384.  * Parameters and other definitions
  385.  *
  386.  */
  387.  
  388. #define INIT_H_SIZE    4            /* default histogram size        */
  389.  
  390. #define TTY_IMM        0                /* transition types            */
  391. #define TTY_EXP        1
  392. #define    TTY_DET        2
  393. #define TTY_NRM        3
  394. #define TTY_BIM        4
  395.  
  396. #define EPSILON        1e-12            /* used in zero-tests for fp-numbers */
  397.  
  398. #ifdef mainpgm                    /* main program ?            */
  399. #define cdext                    /* define data struct.            */
  400. #define dinit(x) = x                /* var initialize            */
  401. #else
  402. #define cdext extern                /* declare data struct.            */
  403. #define dinit(x)                /* no var init                */
  404. #endif
  405. #define _ ,
  406.  
  407. /******************** Data structure definitions ********************/
  408.  
  409. struct transition {
  410.     char        *name;            /* transition name */
  411.     unsigned        type:2;            /* transition type */
  412.     unsigned short    ena_cnt;        /* enable count = #of conditions NOT met to fire :
  413.                            0: the transition can fire */
  414.     unsigned short    ini_ena;        /* initial enable count */
  415.     double        delay;            /* inverse of rate (saves some div's) */
  416.     long        prob;            /* rescaled probablility (for immediate transition only) */
  417.     unsigned long    fire_cnt;        /* # of times the transition fired */
  418.     unsigned long    tot_fire_cnt;        /* total # of times the transition fired */
  419.     
  420.     struct transition    *prev, *next;        /* forw/backw pointer for event queue */
  421.     double        t_fire;            /* time scheduled to fire */
  422.  
  423.     double        sum, sum_sq;        /* for rate computation */
  424.     
  425.     void        (*f_func)();        /* pointer to fire function */
  426. };
  427.  
  428. struct hist {                    /* histogram element */
  429.     double        prob;            /* accumulated time within one generation */
  430.     double        sum;            /* sum (prob) */
  431.     double        sum_sq;            /* sum (prob^2) */
  432.     double        sum_cr;            /* sum (prob * t(gen)) */
  433. };
  434.  
  435. struct place {
  436.     char        *name;            /* name of place */
  437.     unsigned short    ini_mrk, cur_mrk;    /* initial & current #of marks */
  438.     unsigned short    max_mrk;        /* max number of marks (for histogram size) */
  439.     double        t_last;            /* time of last change */
  440.     struct hist        *H;            /* histogram structure */
  441. };
  442.  
  443. struct parameter {                /* generic parameter */
  444.     char        *name;            /* name (to be accessed via command line) */
  445.     unsigned        type:1;            /* 0: int (marking), 1: double (rate) */
  446.     unsigned short    n_used;            /* #of incarnations */
  447.     unsigned short    ind;            /* index to pointer array */
  448.     double        value;            /* current value */
  449. };
  450.  
  451. struct result {
  452.     char        *name;            /* name of result */
  453.     unsigned        type:2;            /* 0: dimensionless (E,P) 1: timed (D) 2: rate (F) */
  454.     double        t_last;            /* time of last change */
  455.     double        cur;            /* current value */
  456.     double        acc;            /* accumulator */
  457.  
  458.     double        sum;            /* sum (prob) */
  459.     double        sum_sq;            /* sum (prob^2) */
  460.     double        sum_cr;            /* sum (prob * t(gen)) */
  461.  
  462.     void        (*upd_fnctn)();        /* update function */
  463. };
  464.  
  465. /******************** Storage definitions ********************/
  466.  
  467. cdext double        clock dinit(0.0);    /* simulation time */
  468. cdext double        total_clock dinit(0.0);    /* accumulated simulation time */
  469. cdext double        total_sq_clock dinit(0.0);    /* accumulated simulation time^2 */
  470. cdext struct transition    *top dinit(0);        /* top of fire queue */
  471. cdext struct transition    *i_top dinit(0);    /* top of fire queue (immediate transitions) */
  472. cdext long        i_prob_acc dinit(0);    /* total probability of immediate transitions */
  473.  
  474.                         /* bimodal distribution control: */
  475. /*
  476.  *  Transition delays alternate between the nominal delay (= same as for an deterministic transition)
  477.  *  and an alternate delay. The ratio is globally controlled as is the alternate delay.
  478.  *  The ratio may vary between 0 (= det. delay only) and 100 (= alt. delay only).
  479.  *  The alternate delay is experessed relative to the det. delay: 0.5 takes half the time,
  480.  *  2.0 takes twice the nominal delay.
  481.  */
  482. cdext int        bim_ratio dinit(50);    /* %of times the alternate delay is used */
  483. cdext double        bim_alt dinit(0.5);    /* alternate delay (the primary is 1.0) */
  484.  
  485.  
  486. extern struct parameter    PARAMETER[];        /* paramerter */
  487. extern unsigned long    n_parameters;
  488. extern double        *d_param[];
  489. extern unsigned short    *i_param[];
  490.  
  491. extern struct transition TRANSITION[];        /* transitions */
  492. extern unsigned long    n_transitions;
  493.  
  494. extern struct place     PLACE[];        /* places */
  495. extern unsigned long    n_places;
  496.  
  497. extern struct result    RESULT[];        /* results */
  498. extern unsigned long    n_results;
  499.  
  500. extern struct transition *TBUF[];        /* temporary list of all enabled transitions */
  501.  
  502. #define DEQUEUE_X_TR(x)    {if (x.prev) x.prev->next = x.next; else top = x.next;\
  503.              if (x.next) x.next->prev = x.prev;}
  504.  
  505. #define DEQUEUE_I_TR(x)    {if (x.prev) x.prev->next = x.next; else i_top = x.next;\
  506.              if (x.next) x.next->prev = x.prev;\
  507.              i_prob_acc -= x.prob;}
  508.  
  509. #define ENQUEUE_I_TR(x)    {x.prev = 0;\
  510.              if (x.next = i_top) i_top->prev = &(x);\
  511.              i_top = &(x);\
  512.              i_prob_acc += x.prob;}
  513.  
  514. cdext FILE        *dstf;            /* output and results go here */
  515. cdext FILE        *yyin;            /* for future use (standart get_opt feature) */
  516.  
  517. double            acc_dwt();        /* accumulate dwell time */
  518.  
  519. /******************** Option processing (the usual chore) ********************/
  520.  
  521. cdext long        n_fire dinit(10000);    /* # of transition fireings        */
  522. cdext long        n_rgen dinit(5);    /* # of regenerations            */
  523. cdext long        random_seed dinit(123);    /* seed for random number generation */
  524. cdext char        *comment dinit(0);    /* optional comment            */
  525. cdext char        *out_file dinit(0);    /* optional output file            */
  526.  
  527.             /* basics */
  528. #define FIRE 0x0001                /* #of fireing per generation        */
  529. #define RGEN 0x0002                /* #of regeneration cycles        */
  530.  
  531.             /* control */
  532. #define VERB 0x0010                /* verbose option            */
  533. #define BM_R 0x0020                /* bimodal ratio (0..100)        */
  534. #define BM_A 0x0040                             /* bimodal alternate delay        */
  535.             /* misc */
  536. #define COM  0x0100                /* comment supplied            */
  537. #define OUTF 0x0200                /* output file supplied            */
  538. #define SEED 0x0400                /* seed for random number gen        */
  539.  
  540.             /* app-specific */
  541. #define PARM 0x1000                /* load (user interpret)        */
  542.  
  543. cdext unsigned long OPTV dinit (0);        /* option vector            */
  544.  
  545. struct options {                /* list of program options        */
  546.     char c;                    /* mnemonic character            */
  547.     unsigned bc;                    /* bit code                */
  548.     char ty;                    /* type: 0=option 1=var 2=string 3=parameter */
  549.     char **s;                    /* string destination            */
  550.     long *x;                    /* variable destination            */
  551.     unsigned cf;                /* conflicting option            */
  552.     double *d;                    /* floating point option        */
  553. } optv[]
  554. #ifdef mainpgm
  555.     = {
  556.     {'b', BM_R, 1, 0, &bim_ratio, 0, 0},
  557.     {'a', BM_A, 6, 0, 0, 0, &bim_alt},
  558.     {'v', VERB, 0, 0, 0, 0, 0},
  559.     {'f', FIRE, 1, 0, &n_fire, 0, 0},
  560.     {'r', RGEN, 1, 0, &n_rgen, 0, 0},
  561.     {'s', SEED, 1, 0, &random_seed, 0, 0},
  562.     {'c', COM, 2, &comment, 0, 0, 0},
  563.     {'o', OUTF, 2, &out_file, 0, 0, 0},
  564.     {'p', PARM, 5, 0, 0, 0, 0}, 
  565.      {0, 0, 0, 0, 0, 0, 0}}
  566. #endif
  567.                         ;
  568.  
  569.  
  570.  
  571. #undef cdext
  572. #undef dinit
  573. #undef _
  574. !E!O!F!
  575. #
  576. # type    sh /usru1/agn/gspn/../gs.shar   to unpack this archive.
  577. #
  578. echo extracting gs_main.c...
  579. cat >gs_main.c <<'!E!O!F!'
  580. /************************************************************************\
  581. *                                                                        *
  582. *  GS: A Generalized, stochastic petri net Simulator                     *
  583. *      V0.01      March 1989      Andreas Nowatzyk (agn@unh.cs.cmu.edu)  *
  584. *      Carnegie-Mellon Univerity, School of Computer Science             *
  585. *      Schenley Park, Pittsburgh, PA 15213                               *
  586. *                                                                        *
  587. \************************************************************************/
  588.  
  589. /* GSPN simulator, main part */
  590.  
  591. #include <stdio.h>
  592. #include "gs.h"
  593.  
  594. main(argc, argv)
  595.     int argc;
  596.     char *argv[];
  597. {
  598.     register int i, j;
  599.  
  600.     get_opt(argc, argv);            /* process comand line */
  601.     init();                    /* initialize data structures */
  602.  
  603.     if (n_rgen < 2 || n_fire < 1000)
  604.     err ("Bogus rgen/fire parameters\n");
  605.  
  606.     for (i = 0; i < n_rgen; i++) {
  607.     reset_net();
  608.     fire(n_fire);
  609.     cleanup();
  610.     }
  611.  
  612.     print_result();
  613.  
  614.     exit(0);                    /* successful exit */
  615. }
  616.  
  617. err(s)
  618.     char *s;
  619. {
  620.     fprintf (stderr, "Error: %s\n", s);
  621.     exit(1);
  622. }
  623.  
  624. init ()                        /* initialize data structures */
  625. /*
  626.  *  0. initialize random number generation
  627.  *  1. allocate histogram space (and zero it)
  628.  *  2. compute intergerized transition probabilities for
  629.  *     immediate transitions. make sure that any additive combination
  630.  *     of these un-normalized probablilities does not exceed +2^31,
  631.  *     also insure that no probablility is == 0
  632.  */
  633. {
  634.     register int i, j;
  635.     register double s;
  636.     register struct place *p;
  637.     register struct hist *h;
  638.     register struct transition *t;
  639.  
  640.     if (bim_ratio < 0 || bim_ratio > 100 || bim_alt < 0.0)
  641.     err ("bad -b or -a option");
  642.  
  643.     rnd_init(random_seed);
  644.  
  645.     for(i = n_places, p = PLACE; i--; p++) {
  646.     j = p->ini_mrk + 1;
  647.     if (j < INIT_H_SIZE) j = INIT_H_SIZE;
  648.     p->max_mrk = j;
  649.     p->H = h = (struct hist *) malloc (j * sizeof (struct hist));
  650.     while (j--) {
  651.         h->sum = 0.0;
  652.         h->sum_sq = 0.0;
  653.         h->sum_cr = 0.0;
  654.         h++;
  655.     }
  656.     }
  657.  
  658.     s = 0.0;
  659.     for (i = n_transitions, t = TRANSITION, j = 0; i--; t++)
  660.     if (t->type == TTY_IMM) {
  661.         j++;
  662.         s += 1.0 / t->delay;
  663.     }
  664.     if (j) {                    /* worry about this only if there are imm transitions */
  665.     if (s < EPSILON)
  666.         err ("Unreasonable transition rates for immediate transitions");
  667.     s = 268435456.0 / s;            /* scale */
  668.     for (i = n_transitions, t = TRANSITION; i--; t++)
  669.         if (t->type == TTY_IMM) {
  670.         t->prob = 0.5 + s / t->delay;
  671.         if (t->prob < 1)
  672.             t->prob = 1;
  673.         }
  674.     }
  675. }
  676.  
  677. reset_net()                    /* reset net to initial state */
  678. /*
  679.  *  1. reset places to original # of tokens
  680.  *  2. reset clock & queue
  681.  *  3. reset transition enable counts
  682.  *  4. initialize fire-queue
  683.  *  5. reset result accumulators & state
  684.  */
  685. {
  686.     register int    i, j;
  687.     register struct place *p;
  688.     register struct hist *h;
  689.     register struct transition *t;
  690.     register struct result *r;
  691.  
  692.     for (i = n_places, p = PLACE; i--; p++) {
  693.     p->cur_mrk = p->ini_mrk;
  694.     p->t_last = 0.0;
  695.     for (j = p->max_mrk, h = p->H; j--; h++)
  696.         h->prob = 0.0;
  697.     }
  698.  
  699.     top = 0;
  700.     i_top = 0;
  701.     i_prob_acc = 0;
  702.     clock = 0.0;
  703.  
  704.     for (i = n_transitions, t = TRANSITION; i--; t++) {
  705.     t->fire_cnt = 0;
  706.     if (!(t->ena_cnt = t->ini_ena)) {
  707.         switch (t->type) {
  708.         case TTY_IMM:
  709.         enqueue_i_tr(t);
  710.         break;
  711.         case TTY_EXP:
  712.         enqueue_e_tr(t);
  713.         break;
  714.         case TTY_DET:
  715.         enqueue_d_tr(t);
  716.         break;
  717.         case TTY_BIM:
  718.         enqueue_b_tr(t);
  719.         break;
  720.         case TTY_NRM:
  721.         enqueue_n_tr(t);
  722.         break;
  723.         }
  724.     }
  725.     }
  726.  
  727.     for (i = n_results, r = RESULT; i--; r++) {
  728.     if (r->type)
  729.         continue;
  730.     r->t_last = 0.0;
  731.     r->acc = 0.0;
  732.     (*(r->upd_fnctn)) ();
  733.     }
  734. }
  735.  
  736. add_H_space (p)                    /* increase the histogram size */
  737.     register struct place *p;
  738. {
  739.     register int i;
  740.     register struct hist *h;
  741.  
  742.     i = INIT_H_SIZE + p->max_mrk / 2;
  743.     p->H = h = (struct hist *) realloc (p->H, (p->max_mrk + i) * sizeof(struct hist));
  744.     h += p->max_mrk;
  745.     p->max_mrk += i;
  746.     while (i--) {
  747.         h->prob = 0.0;
  748.         h->sum = 0.0;
  749.         h->sum_sq = 0.0;
  750.         h->sum_cr = 0.0;
  751.         h++;
  752.     }
  753. }
  754.  
  755. enqueue_i_tr (t)                /* add an immediate transition to fire queue */
  756.     register struct transition *t;
  757. {
  758.     t->prev = 0;
  759.     if (t->next = i_top)
  760.     i_top->prev = t;
  761.     i_top = t;
  762.     i_prob_acc += t->prob;
  763. }
  764.  
  765. enqueue_d_tr (t)                /* add an deterministic transition to fire queue */
  766.     register struct transition *t;
  767. {
  768.     register double tf;
  769.     register struct transition *q;
  770.  
  771.     t->t_fire = tf = clock + t->delay;
  772.  
  773.     if (q = top) {
  774.     while (q->t_fire < tf) {
  775.         if (!q->next) {            /* end of queue: append at end */
  776.         q->next = t;
  777.         t->prev = q;
  778.         t->next = 0;
  779.         return;
  780.         }
  781.         q = q->next;
  782.     }
  783.  
  784.     t->next = q;                /* insert before q */
  785.     if (!(t->prev = q->prev))        /* ... happen to be top */
  786.         top = t;
  787.     else
  788.         q->prev->next = t;
  789.     q->prev = t;
  790.     } else {                    /* virgin queue: insert at top */
  791.     top = t;
  792.     t->next = 0;
  793.     t->prev = 0;
  794.     }
  795. }
  796.  
  797. enqueue_e_tr (t)                /* add an deterministic transition to fire queue */
  798.     register struct transition *t;
  799. {
  800.     register double tf;
  801.     double rnd_nedi();
  802.     register struct transition *q;
  803.  
  804.     t->t_fire = tf = clock + rnd_nedi(t->delay);
  805.  
  806.     if (q = top) {
  807.     while (q->t_fire < tf) {
  808.         if (!q->next) {            /* end of queue: append at end */
  809.         q->next = t;
  810.         t->prev = q;
  811.         t->next = 0;
  812.         return;
  813.         }
  814.         q = q->next;
  815.     }
  816.  
  817.     t->next = q;                /* insert before q */
  818.     if (!(t->prev = q->prev))        /* ... happen to be top */
  819.         top = t;
  820.     else
  821.         q->prev->next = t;
  822.     q->prev = t;
  823.     } else {                    /* virgin queue: insert at top */
  824.     top = t;
  825.     t->next = 0;
  826.     t->prev = 0;
  827.     }
  828. }
  829.  
  830. enqueue_b_tr (t)                /* add a bimodal distr. transition to fire queue */
  831.     register struct transition *t;
  832. {
  833.     register double tf;
  834.     register struct transition *q;
  835.  
  836.     if (bim_ratio <= rnd_ri(100))
  837.     tf = clock + t->delay;
  838.     else
  839.     tf = clock + t->delay * bim_alt;
  840.  
  841.     t->t_fire = tf;
  842.  
  843.     if (q = top) {
  844.     while (q->t_fire < tf) {
  845.         if (!q->next) {            /* end of queue: append at end */
  846.         q->next = t;
  847.         t->prev = q;
  848.         t->next = 0;
  849.         return;
  850.         }
  851.         q = q->next;
  852.     }
  853.  
  854.     t->next = q;                /* insert before q */
  855.     if (!(t->prev = q->prev))        /* ... happen to be top */
  856.         top = t;
  857.     else
  858.         q->prev->next = t;
  859.     q->prev = t;
  860.     } else {                    /* virgin queue: insert at top */
  861.     top = t;
  862.     t->next = 0;
  863.     t->prev = 0;
  864.     }
  865. }
  866.  
  867. enqueue_n_tr (t)                /* add a normal distr. transition to fire queue */
  868.     register struct transition *t;
  869. {
  870.     register double tf;
  871.     double rnd_01d();
  872.     register struct transition *q;
  873.  
  874.     t->t_fire = tf = clock + t->delay * rnd_01d();
  875.  
  876.     if (q = top) {
  877.     while (q->t_fire < tf) {
  878.         if (!q->next) {            /* end of queue: append at end */
  879.         q->next = t;
  880.         t->prev = q;
  881.         t->next = 0;
  882.         return;
  883.         }
  884.         q = q->next;
  885.     }
  886.  
  887.     t->next = q;                /* insert before q */
  888.     if (!(t->prev = q->prev))        /* ... happen to be top */
  889.         top = t;
  890.     else
  891.         q->prev->next = t;
  892.     q->prev = t;
  893.     } else {                    /* virgin queue: insert at top */
  894.     top = t;
  895.     t->next = 0;
  896.     t->prev = 0;
  897.     }
  898. }
  899.  
  900. fire (n)                    /* fire n-times */
  901.     register unsigned long n;
  902. {
  903.     register double tf;
  904.     register struct transition **q, *t;
  905.     register long i;
  906.  
  907.     while (n--) {                /* fire loop */
  908.  
  909.     if (t = i_top) {            /* at least one enabled i-transition */
  910.         if (!(t->next)) {            /* only one! */
  911.         (*(t->f_func)) ();
  912.         continue;            /* fire and done! */
  913.         }
  914. /*
  915.  * Note: the i-trans selection method is moderately tricky, but correct and fast.
  916.  */
  917.         i = rnd_ri(i_prob_acc);        /* roll the dice! */
  918.         while (0 <= (i -= t->prob))
  919.         t = t->next;
  920.         (*(t->f_func)) ();            /* fire the choosen one */
  921.         continue;
  922.     }
  923.  
  924.     if (!(t = top))
  925.         dead_net(n);
  926.  
  927.     clock = tf = t->t_fire;            /* advance clock */
  928.     q = TBUF;
  929.  
  930.     *q = t;
  931.     i = 1;
  932.     for (t = t->next; t && t->t_fire == tf; i++, t = t->next)
  933.         *(++q) = t;                /* collect all enabled transitions */
  934.     
  935.     if (i > 1)                /* fire a random one if more than 1 is enabled */
  936.         (*(TBUF[rnd_ri(i)]->f_func))();
  937.     else
  938.         (*(TBUF[0]->f_func)) ();
  939.     }
  940. }
  941.  
  942. dead_net(n)                    /* dead-locked, print final marking */
  943.     int n;
  944. {
  945.     register int i;
  946.     register struct place *p;
  947.  
  948.     printf ("No enabled transition: time=%.2f  fire-count=%d/%d\n", clock, n_fire - n, n_fire);
  949.     for (i = n_places,  p = PLACE; i--; p++)
  950.     printf("Place '%s': %d token\n", p->name, p->cur_mrk);
  951.  
  952.     err("No enabled transition (deadlock)");
  953. }
  954.  
  955. cleanup ()                    /* terminate fire */
  956. /*
  957.  *  1. accumulate total simulation time
  958.  *  2. update place-statistic to current time
  959.  *  3. add up fire counts and rates
  960.  *  4. update result statistic
  961.  */
  962. {
  963.     register int i, j;
  964.     register struct place *p;
  965.     register struct transition *tr;
  966.     register struct hist *h;
  967.     register struct result *r;
  968.     register double t, c, s;
  969.     
  970.     total_clock += c = clock;
  971.     total_sq_clock += c * c;
  972.  
  973.     if (c < EPSILON)
  974.     err("Simulation did not consume time");
  975.     s = 1.0 / c;
  976.  
  977.     for (i = n_places,  p = PLACE; i--; p++) {
  978.     h = p->H;
  979.     h[p->cur_mrk].prob += clock - p->t_last;
  980.     for (j = p->max_mrk; j--; h++) {
  981.         t = h->prob;
  982.         h->sum += t;
  983.         h->sum_sq += t * t;
  984.         h->sum_cr += t * c;
  985.     }
  986.     }
  987.  
  988.     for(i = n_transitions, tr = TRANSITION; i--; tr++) {
  989.     tr->tot_fire_cnt += j = tr->fire_cnt;
  990.     t = j * s;
  991.     tr->sum += t;
  992.     tr->sum_sq += t * t;
  993.     }
  994.  
  995.     for (i = n_results,  r = RESULT; i--; r++) {
  996.     if (r->type) {
  997.         (*(r->upd_fnctn))();
  998.     } else {
  999.         t = r->acc + r->cur * (clock - r->t_last);
  1000.         r->sum += t;
  1001.         r->sum_sq += t * t;
  1002.         r->sum_cr += t * c;
  1003.     }
  1004.     }
  1005. }
  1006.  
  1007. print_result ()                    /* you guessed it */
  1008. {
  1009.     register int i, j;
  1010.     register struct place *p;
  1011.     register struct transition *t;
  1012.     register struct hist *h;
  1013.     register struct result *rp;
  1014.     register double x, c, q, r, s;
  1015.     double sqrt(), stud_t995();
  1016.  
  1017.     if (total_clock < EPSILON)
  1018.     err ("No timed transitions fired");
  1019.  
  1020.     q = stud_t995(n_rgen - 1);
  1021.     r = n_rgen / (total_clock * total_clock * (n_rgen - 1));
  1022.     s = 1.0 / total_clock;
  1023.  
  1024.     for (i = n_places, p = PLACE; i--; p++) {
  1025.     printf ("Place '%s':\n", p->name);
  1026.     for(j = 0, h = p->H; j < p->max_mrk; h++, j++) {
  1027.         if (h->sum < EPSILON)
  1028.         continue;
  1029.  
  1030.                         /* the next is practically verbatim from Chiola's original */
  1031.         x = h->sum * s;
  1032.         c = h->sum_sq + x * (x * total_sq_clock - 2 * h->sum_cr);
  1033.         c = q * sqrt(c * r);
  1034.  
  1035.         printf ("\tP(%d) = %8.6f (+/- %8.6f)\n", j, x, c);
  1036.     }
  1037.     }
  1038.  
  1039.     for (i = n_results, rp = RESULT; i--; rp++) {
  1040.     if (rp->type) {                /* dwell-time */
  1041.         x = rp->sum / n_rgen;
  1042.         c = rp->sum_sq - x * rp->sum;
  1043.         c = q * sqrt(c / (n_rgen * (n_rgen - 1)));
  1044.         printf ("%s = %8.6f (+/- %8.6f) [%s]\n", rp->name, x, c, (rp->type == 1) ? "time units" : "fireing / time unit");
  1045.     } else {                /* probabilities and expectations */
  1046.         x = rp->sum * s;
  1047.         c = rp->sum_sq + x * (x * total_sq_clock - 2 * rp->sum_cr);
  1048.         c = q * sqrt(c * r);
  1049.         printf ("%s = %8.6f (+/- %8.6f)\n", rp->name, x, c);
  1050.     }
  1051.     }
  1052.  
  1053.     for(i = n_transitions, t = TRANSITION; i--; t++) {
  1054.     x = t->sum / n_rgen;
  1055.     c = t->sum_sq - x * t->sum;
  1056.     c = q * sqrt(c / (n_rgen * (n_rgen - 1)));    
  1057.     printf("Transition %s : %8.6f (+/- %8.6f) [fireing / time-unit]\n", t->name, x, c);
  1058.     }
  1059. }
  1060.  
  1061. /* #define INP_FILE 1 */    /* expect an input file         */
  1062.  
  1063. get_opt (argc, argv)                /* process arguments     */
  1064.     int argc;
  1065.     char *argv[];
  1066. {
  1067.     register int     i, j, k, aty;
  1068.     double d, *dbl;
  1069.     int l;
  1070.     struct parameter *pp;
  1071.     long    *var;
  1072.     char    opt, **str, fname[82];
  1073.     char *infn = 0;                /* input file name         */
  1074.     char *outfn = 0;                /* output file name         */
  1075.  
  1076.     aty = 0;                    /* expect no sub argument        */
  1077.     for (i = 1; i < argc; i++) {        /* scan arguments            */
  1078.     if (argv[i][0] == '-' && !aty) {    /* got an option            */
  1079.  
  1080.         for (j = 1; argv[i][j]; j++) {    /* scan option string            */
  1081.         opt = argv[i][j];
  1082.         for (k = 0; optv[k].c; k++)
  1083.             if (opt == optv[k].c) {    /* found option                */
  1084.             if (OPTV & optv[k].cf) {
  1085.                 fprintf(stderr, "Option '%c' conflicts with earlier option\n", opt);
  1086.                 goto error;
  1087.             }
  1088.             OPTV |= optv[k].bc;
  1089.             if (optv[k].ty) {
  1090.                 if (aty) {
  1091.                 fprintf(stderr, "Ambigious option/argument combination\n");
  1092.                 goto error;
  1093.                 
  1094.                 }
  1095.                 aty = optv[k].ty;
  1096.                 str = optv[k].s;
  1097.                 var = optv[k].x;
  1098.                 dbl = optv[k].d;
  1099.             }
  1100.             break;
  1101.             }
  1102.         if (!optv[k].c) {
  1103.             fprintf(stderr, "Unknown option\n");
  1104.             goto error;
  1105.         }
  1106.         }
  1107.     } else {                /* got an argument            */
  1108.         switch (aty) {
  1109.         case 6:                /*** double ***/
  1110.         if (1 != sscanf(argv[i], "%lf", dbl))
  1111.             goto error;
  1112.         aty = 0;
  1113.         break;
  1114.         case 5:                /*** parameter ***/
  1115.         for (j = n_parameters, pp = PARAMETER; j--; pp++)
  1116.             if (!strcmp(argv[i], pp->name)) {
  1117.             if(pp->type)
  1118.                 aty = 4;        /* positive double param */
  1119.             else
  1120.                 aty = 3;        /* positive int param */
  1121.             break;
  1122.             }
  1123.         if (j < 0) {
  1124.             fprintf(stderr, "Undefined parameter\n");
  1125.             goto error;
  1126.         }
  1127.         break;
  1128.         case 4:                /*** convert a double > 0 ***/
  1129.         if (1 != sscanf(argv[i], "%lf", &d) || d < 0.0) {
  1130.             fprintf(stderr, "Invalid value for '%s'\n", pp->name);
  1131.             goto error;
  1132.         }
  1133.         if (d < EPSILON) d = 1e20;    /* approximate infinite delay */
  1134.         else d = 1.0 / d;
  1135.         pp->value = d;
  1136.         for (j = pp->ind, k = pp->n_used; k--; j++)
  1137.             *d_param[j] = d;
  1138.         aty = 0;
  1139.         break;
  1140.         case 3:                /*** integer > 0 parameter ***/
  1141.         if (1 != sscanf(argv[i], "%d", &l) || l < 0) {
  1142.             fprintf(stderr, "Invalid value for '%s'\n", pp->name);
  1143.             goto error;
  1144.         }
  1145.         j = pp->ind;
  1146.         if ((!*i_param[j]) != (!l)) {
  1147.             fprintf(stderr, "Can't switch between 0 and non-0 #of tokens\n");
  1148.             goto error;
  1149.         }
  1150.         pp->value = l;
  1151.         for (k = pp->n_used; k--; j++)
  1152.             *i_param[j] = l;
  1153.         aty = 0;
  1154.         break;
  1155.         case 2:                /*** string sub-argument ***/
  1156.         *str = argv[i];
  1157.         aty = 0;
  1158.         break;
  1159.         case 1:                /*** integer sub-argument ***/
  1160.         if (1 != sscanf(argv[i], "%ld", var))
  1161.             goto error;
  1162.         aty = 0;
  1163.         break;
  1164.         default:                /*** unspecified arg (filename) ***/
  1165. #ifdef INP_FILE
  1166.         infn = argv[i];
  1167.         i++;
  1168. #endif
  1169.         if (i < argc) {            /* output file name present ?     */
  1170.             if ('-' == argv[i][0] || (i + 1) < argc)
  1171.             goto error;
  1172.             outfn = argv[i];
  1173.         }
  1174.         }
  1175.     }
  1176.     }
  1177.  
  1178.     if (infn) {
  1179.     yyin = fopen(infn, "r");
  1180.     if (!yyin) {
  1181.         fprintf(stderr, "Could not open '%s' for read\n", infn);
  1182.         exit(1);
  1183.     }
  1184.     } else
  1185.     yyin = stdin;
  1186.  
  1187.     if (outfn) {
  1188.     dstf = fopen(outfn, "w");
  1189.     if (!dstf) {
  1190.         fprintf(stderr, "Could not open '%s' for write\n", outfn);
  1191.         exit(1);
  1192.     }
  1193.     } else
  1194.     dstf = stdout;
  1195.  
  1196.     return;            /* options are ok         */
  1197.  
  1198. error:                /* some trouble with the arguments */
  1199.     fprintf(stderr, "gs [-");
  1200.     for (i = 0; optv[i].c; i++)
  1201.     fprintf(stderr, "%c", optv[i].c);
  1202.     fprintf(stderr, "] [input-file] [output-file]\n");
  1203.  
  1204.     exit(1);
  1205. }
  1206.  
  1207. double stud_t995 (n)        /* approximation to Student's T-percentiles */
  1208.     int n;
  1209. {
  1210.     static double tab[30] = {
  1211.     63.657, 9.925, 5.841, 4.604, 4.032, 3.707, 3.499, 3.355, 3.250, 3.169,
  1212.      3.106, 3.055, 3.012, 2.977, 2.947, 2.921, 2.898, 2.878, 2.861, 2.845,
  1213.      2.831, 2.819, 2.807, 2.797, 2.787, 2.779, 2.771, 2.763, 2.756, 2.750
  1214.     };
  1215.  
  1216.     if (n < 1)
  1217.     err ("Student's T percentiles not defined for n < 1");
  1218.  
  1219.     if (n <= 30)
  1220.     return tab[n - 1];
  1221.  
  1222.     if (n > 200)
  1223.     return 2.576;
  1224.  
  1225.     n -= 30;
  1226.     if (n  < 10)
  1227.     return 2.750 - n * 0.0046;
  1228.     n -= 10;
  1229.     if (n < 20)
  1230.     return 2.704 - n * 0.0022;
  1231.     n -= 20;
  1232.     if (n < 60)
  1233.     return 2.660 - n * 0.0007;
  1234.     n -= 60;
  1235.     return 2.617 - n * 0.0005;
  1236. }
  1237.  
  1238. double acc_dwt(p)                /* accumulate dwell time */
  1239.     register struct place *p;
  1240. {
  1241.     register double t = 0.0;
  1242.     register struct hist *h = p->H + 1;
  1243.     register int i;
  1244.  
  1245.     for(i = 1; i < p->max_mrk; i++, h++)
  1246.     t += i * h->prob;
  1247.  
  1248.     return t;
  1249. }
  1250. !E!O!F!
  1251. #
  1252. # type    sh /usru1/agn/gspn/../gs.shar   to unpack this archive.
  1253. #
  1254. echo extracting gs_pp.c...
  1255. cat >gs_pp.c <<'!E!O!F!'
  1256. /* main part of gs-preprocessor */
  1257.  
  1258. static struct parameter *PR = 0;        /* parameter structure */
  1259. static int n_PR = 0, max_PR = 0;
  1260.  
  1261. static struct place *PL = 0, *cur_PL;        /* place structure */
  1262. static int n_PL = 0, max_PL = 0;
  1263.  
  1264. static struct transition *TR = 0, *cur_TR;    /* transition structure */
  1265. static int n_TR = 0, max_TR = 0;
  1266.  
  1267. static struct result *RS = 0;            /* result struture */
  1268. static int n_RS = 0,  max_RS = 0;
  1269.  
  1270. static int error_cnt = 0;            /* error counter */
  1271.  
  1272. static int result_type;                /* result type */
  1273.  
  1274. #define EPS        1e-12            /* for FP-zero tests */
  1275.  
  1276.  
  1277.  
  1278. main ()
  1279. {
  1280.     yyparse();                    /* parse the input */
  1281.     check();                    /* sanity check */
  1282.  
  1283.     if (error_cnt)
  1284.     exit(1);                /* exit in case of errors */
  1285.  
  1286.     build_place();                /* emitt simulator structures */
  1287.     build_trans();
  1288.     build_param();
  1289.     build_tfunc();
  1290.     build_rslts();
  1291.     build_ffunc();
  1292.  
  1293.     exit(0);                    /* done! */
  1294. }
  1295.  
  1296. yyerror (s)                    /* error printer         */
  1297.     char *s;
  1298. {
  1299.     error_cnt++;
  1300.     fprintf (stderr, "%s, line %d: %s\n", src_file, yylineno, s);
  1301. }
  1302.  
  1303. struct parameter *find_param (s)        /* find a parameter */
  1304.     register char *s;
  1305. {
  1306.     register int i;
  1307.     register struct parameter *p;
  1308.  
  1309.     for (i = n_PR,  p = PR; i--; p++)
  1310.     if (!strcmp(s, p->name)) {
  1311.         free(s);
  1312.         return p;
  1313.     }
  1314.  
  1315.     if (n_PR <= max_PR) {            /* need more space */
  1316.     max_PR += 20 + max_PR / 2;
  1317.     if (PR)
  1318.         PR = p = (struct parameter *) realloc (PR,  max_PR * sizeof(struct parameter));
  1319.     else
  1320.         PR = p = (struct parameter *) malloc (max_PR * sizeof(struct parameter));
  1321.     }
  1322.  
  1323.     p += n_PR++;
  1324.     p->name = s;
  1325.     p->defined = 0;
  1326.     p->used = 0;
  1327.     p->max_used = 0;
  1328.     p->ind = 0;
  1329.  
  1330.     return p;
  1331. }
  1332.  
  1333. add_param (s, v)                /* got a new parameter */
  1334.     register char *s;
  1335.     double v;
  1336. {
  1337.     register struct parameter *p = find_param(s);
  1338.  
  1339.     if(p->defined)
  1340.     yyerror("Parameter allready defined");
  1341.     p->defined = 1;
  1342.     p->value = v;
  1343. }
  1344.  
  1345. struct place *find_place(s)                /* locate a place */
  1346.     register char *s;
  1347. {
  1348.     register int    i;
  1349.     register struct place *p;
  1350.  
  1351.     for (i = n_PL, p = PL; i--; p++)            /* see if place is allready defined */
  1352.     if (!strcmp(s, p->name)) {
  1353.         free(s);
  1354.         return p;
  1355.     }
  1356.  
  1357.     if (n_PL >= max_PL) {            /* need more space */
  1358.     max_PL += 50 + max_PL / 2;
  1359.     if (PL)
  1360.         PL = (struct place *) realloc(PL, sizeof(struct place) * max_PL);
  1361.     else
  1362.         PL = (struct place *) malloc(sizeof(struct place) * max_PL);
  1363.     }
  1364.  
  1365.     p = &PL[n_PL++];
  1366.     p->name = s;
  1367.     p->defined = 0;
  1368.     p->input_ptr = 0;
  1369.     p->inhib_ptr = 0;
  1370.     p->result_ptr = 0;
  1371.     p->n_input = 0;
  1372.     p->n_output = 0;
  1373.     return p;
  1374. }
  1375.  
  1376. add_place (s)                    /* got a new place */
  1377.     register char *s;
  1378. {
  1379.     register int    i;
  1380.     register struct place *p = find_place(s);
  1381.  
  1382.     if (p->defined) {
  1383.     yyerror("Place allready defined");
  1384.     return;
  1385.     }
  1386.  
  1387.     cur_PL = p;
  1388.     p->defined = 1;
  1389.     p->mdef = 0;
  1390.     p->marks = 0;
  1391. }
  1392.  
  1393. chg_marks (d)                    /* change number of marks in a place */
  1394.     double d;
  1395. {
  1396.     register int i = d + 0.5;            /* round to an integer */
  1397.  
  1398.     if (i < 0 || cur_PL->mdef)
  1399.     yyerror ("illegal or multiple marking-specification");
  1400.     else {
  1401.     cur_PL->mdef = 1;
  1402.     cur_PL->marks = i;
  1403.     }
  1404. }
  1405.  
  1406. chg_p_marks (s)                    /* change number of marks in a place */
  1407.     char *s;
  1408. {
  1409.     register struct parameter *p = find_param(s);    /* locate parameter */
  1410.  
  1411.     if (cur_PL->mdef || (p->used && p->type))
  1412.     yyerror ("Marking specification problem");
  1413.     else {
  1414.     if (p->used >= p->max_used) {
  1415.         p->type = 0;
  1416.         p->max_used += 10 + p->max_used / 2;
  1417.         if (p->ind)
  1418.         p->ind = (int *) realloc (p->ind, p->max_used * sizeof(int));
  1419.         else
  1420.         p->ind = (int *) malloc (p->max_used * sizeof(int));
  1421.     }
  1422.     cur_PL->mdef = 1;
  1423.     p->ind[p->used++] = cur_PL - PL;
  1424.     }
  1425. }
  1426.  
  1427. struct transition *find_transition(s)
  1428.     register char *s;
  1429. {
  1430.     register int    i;
  1431.     register struct transition *t;
  1432.  
  1433.     for (i = n_TR, t = TR; i--; t++)        /* see if transition is allready defined */
  1434.     if (!strcmp(s, t->name)) {
  1435.         free(s);
  1436.         return t;
  1437.     }
  1438.  
  1439.     if (n_TR >= max_TR) {            /* need more space */
  1440.     max_TR += 50 + max_TR / 2;
  1441.     if (TR)
  1442.         TR = (struct transition *) realloc(TR, sizeof(struct transition) * max_TR);
  1443.     else
  1444.         TR = (struct transition *) malloc(sizeof(struct transition) * max_TR);
  1445.     }
  1446.  
  1447.     t = &TR[n_TR++];
  1448.     t->name = s;                /* set up default transition structure */
  1449.     t->def = 0;
  1450.     t->ddef = 0;
  1451.     t->delay = 1.0;
  1452.     t->depdef = 0;
  1453.     t->depend = 1;
  1454.     t->n_input = 0;
  1455.     t->n_output = 0;
  1456.     t->n_inhib = 0;
  1457.     t->input_ptr = 0;
  1458.     t->output_ptr = 0;
  1459.     t->inhib_ptr = 0;
  1460.  
  1461.     return t;
  1462. }
  1463.  
  1464. add_transition (s)                /* got a new transition */
  1465.     char *s;
  1466. {
  1467.     register struct transition *t = find_transition(s);
  1468.  
  1469.     if (t->def)
  1470.     yyerror("Transition multiply defined");
  1471.     t->def = 1;
  1472.     cur_TR = t;
  1473. }
  1474.  
  1475. set_type (t)                    /* define the transition type */
  1476.     int t;
  1477. {
  1478.     cur_TR->type = t;
  1479. }
  1480.  
  1481. chg_depend (d)                    /* change the transition delay */
  1482.     double d;
  1483. {
  1484.     if (cur_TR->depdef || d < 0.0)
  1485.     yyerror("dependency definition problem");
  1486.     else {
  1487.     cur_TR->depdef = 1;
  1488.     cur_TR->depend = d;
  1489.     if (cur_TR->depend != 1)
  1490.         yyerror("Sorry, only depency = 1 supported");
  1491.     }
  1492. }
  1493.  
  1494. chg_rate (d)                    /* change the transition rate */
  1495.     double d;
  1496. {
  1497.     if (cur_TR->ddef || d <= EPS) 
  1498.     yyerror("rate definition problem");
  1499.     else {
  1500.     cur_TR->ddef = 1;
  1501.     cur_TR->delay = 1.0 / d;
  1502.     }
  1503. }
  1504.  
  1505. chg_p_rate (s)                    /* change the transition rate parameter */
  1506.     char *s;
  1507. {
  1508.     register struct parameter *p = find_param(s);    /* locate parameter */
  1509.  
  1510.     if (cur_TR->ddef || (p->used && !p->type)) 
  1511.     yyerror("rate definition problem");
  1512.     else {
  1513.     if (p->used >= p->max_used) {
  1514.         p->type = 1;
  1515.         p->max_used += 10 + p->max_used / 2;
  1516.         if (p->ind)
  1517.         p->ind = (int *) realloc (p->ind, p->max_used * sizeof(int));
  1518.         else
  1519.         p->ind = (int *) malloc (p->max_used * sizeof(int));
  1520.     }
  1521.     p->ind[p->used++] = cur_TR - TR;
  1522.     cur_TR->ddef = 1;
  1523.     }
  1524. }
  1525.  
  1526. add_input (s)                    /* add input to a transition */
  1527.     char *s;
  1528. {
  1529.     register struct list_item *t;
  1530.     register struct place *p = find_place(s);
  1531.  
  1532.     t = (struct list_item *) malloc(sizeof(struct list_item));
  1533.     t->ind = p - PL;
  1534.     t->next = cur_TR->input_ptr;
  1535.     cur_TR->input_ptr = t;
  1536.     cur_TR->n_input++;
  1537.  
  1538.     t = (struct list_item *) malloc(sizeof(struct list_item));
  1539.     t->ind = cur_TR - TR;
  1540.     t->next = p->input_ptr;
  1541.     p->input_ptr = t;
  1542.     p->n_input++;
  1543. }
  1544.  
  1545. add_output (s)                    /* add output to a transition */
  1546.     char *s;
  1547. {
  1548.     register struct list_item *t;
  1549.     register struct place *p = find_place(s);
  1550.  
  1551.     t = (struct list_item *) malloc(sizeof(struct list_item));
  1552.     p->n_output++;
  1553.     t->ind = p - PL;
  1554.     t->next = cur_TR->output_ptr;
  1555.     cur_TR->output_ptr = t;
  1556.     cur_TR->n_output++;
  1557. }
  1558.  
  1559. add_inhib (s)                    /* add inhib to a transition */
  1560.     char *s;
  1561. {
  1562.     register struct list_item *t;
  1563.     register struct place *p = find_place(s);
  1564.  
  1565.     t = (struct list_item *) malloc(sizeof(struct list_item));
  1566.     t->ind = p - PL;
  1567.     t->next = cur_TR->inhib_ptr;
  1568.     cur_TR->inhib_ptr = t;
  1569.     cur_TR->n_inhib++;
  1570.  
  1571.     t = (struct list_item *) malloc(sizeof(struct list_item));
  1572.     t->ind = cur_TR - TR;
  1573.     t->next = p->inhib_ptr;
  1574.     p->inhib_ptr = t;
  1575. }
  1576.  
  1577. check()                        /* sanity check */
  1578. /*
  1579.  * Make sure that:
  1580.  *
  1581.  *  0. See that parameters are defined & used
  1582.  *  1. All places are defined
  1583.  *  2. All places have at least one in/out arc
  1584.  *  3. All transitions have at least one input and one output
  1585.  *     (I can't think of any sensible transition lacking either)
  1586.  *  4. Transition type matches given parameters
  1587.  *     (can't specify a reate for an immediate transition)
  1588.  */
  1589. {
  1590.     register int    i, j, k, *ip;
  1591.     register double d;
  1592.     register struct place *p;
  1593.     register struct transition *t;
  1594.     register struct parameter *pr;
  1595.     char            buf[80];
  1596.  
  1597.     if (n_PL < 1 || n_TR < 1)
  1598.     yyerror ("Need at least 1 place/transition");
  1599.  
  1600.     for(i = n_PR, pr = PR; i--; pr++) {        /* check parameters and insert values */
  1601.     if (!pr->defined) {
  1602.         sprintf(buf, "Undefined parameter '%s'", pr->name);
  1603.         yyerror(buf);
  1604.     }
  1605.     if (pr->type) {                /* rate-parameter */
  1606.         d = pr->value;
  1607.         if (d <= EPS)
  1608.         yyerror ("Negative rate parameter");
  1609.         else {
  1610.         d = 1.0 / d;
  1611.         for (j = pr->used, ip = pr->ind; j--; ip++)
  1612.             TR[*ip].delay = d;
  1613.         }
  1614.     } else {                /* marking parameter */
  1615.         d = pr->value;
  1616.         if (d <= -EPS)
  1617.         yyerror ("Negative marking parameter");
  1618.         else {
  1619.         k = d + 0.5;
  1620.         for (j = pr->used, ip = pr->ind; j--; ip++)
  1621.             PL[*ip].marks = k;
  1622.         }
  1623.     }
  1624.     }
  1625.  
  1626.     for (i = n_PL, p = PL; i--; p++) {
  1627.     if (!p->defined) {
  1628.         sprintf(buf, "Undefined place '%s'", p->name);
  1629.         yyerror(buf);
  1630.     }
  1631.     if (p->n_input < 1 || p->n_output < 1) {
  1632.         sprintf(buf, "Warning: place '%s' has no input/output arc", p->name);
  1633.         yyerror(buf);
  1634.         error_cnt--;
  1635.     }
  1636.     }
  1637.  
  1638.     for (i = n_TR, t = TR; i--; t++) {
  1639.     if (t->n_input < 1 || t->n_output < 1) {
  1640.         sprintf(buf, "Warning: transition '%s' has no input/output", t->name);
  1641.         yyerror(buf);
  1642.         error_cnt--;
  1643.     }
  1644.     }
  1645. }
  1646.  
  1647. build_place ()                    /* produce place structures for simulator */
  1648. /*
  1649.  * Note: the corresponding structure definition is supplied in "gs.h"
  1650.  *
  1651.  */
  1652. {
  1653.     register int    i, j;
  1654.     printf("#define N_PLACES %d\n\n", n_PL);
  1655.  
  1656.     printf("struct place PLACE[N_PLACES] = {\n");
  1657.     for (i = 0; i < n_PL; i++) {
  1658.     if (i)
  1659.         printf(",\n");
  1660.     printf("    {\"%s\", %d, %d, 0, 0.0, 0}", PL[i].name, PL[i].marks, PL[i].marks);
  1661.     }
  1662.     printf("\n};\n\n");
  1663. }
  1664.  
  1665. build_tfunc ()                    /* produce fire-to macros structures for simulator */
  1666. /*
  1667.  * Note: the corresponding structure definition is supplied in "gs.h"
  1668.  *
  1669.  */
  1670. {
  1671.     register int    i, j;
  1672.     register struct list_item *t;
  1673.  
  1674.     for (i = 0; i < n_PL; i++) {
  1675.     printf("#define FIRE_TO%d ", i);
  1676.     if (PL[i].n_input < 1)
  1677.         printf("0.0\n");
  1678.     else {
  1679.         printf("(");
  1680.         for(t = PL[i].input_ptr, j = 0; t; t = t->next)
  1681.         printf("TRANSITION[%d].fire_cnt%s", t->ind, (t->next) ? 
  1682.             ((!(++j % 3)) ? " +\\\n    " : " + ") : ")\n");
  1683.     }
  1684.     }
  1685.     printf("\n");
  1686. }
  1687.  
  1688. build_trans()                    /* build transition structure */
  1689. {
  1690.     register int    i, j;
  1691.     register struct list_item *t;
  1692.     
  1693.     printf("#define N_TRANSITIONS %d\n\n", n_TR);
  1694.  
  1695.     for (i = 0; i < n_TR; i++)
  1696.     printf ("void fire_T%d();\n", i);
  1697.  
  1698.     printf("\nstruct transition TRANSITION[N_TRANSITIONS] = {\n");
  1699.     for (i = 0; i < n_TR; i++) {
  1700.     if (i)
  1701.         printf(",\n");
  1702.  
  1703.     j = 0;                    /* count # of conditions that prevent fire */
  1704.     for (t = TR[i].input_ptr; t; t = t->next)
  1705.         j += PL[t->ind].marks <= 0;
  1706.     for (t = TR[i].inhib_ptr; t; t = t->next)
  1707.         j += PL[t->ind].marks > 0;
  1708.     
  1709.     printf("    {\"%s\", %d, %d, %d, %.12e, 0, 0, 0, 0, 0, 0.0, 0.0, 0.0, fire_T%d}",
  1710.         TR[i].name, TR[i].type, j, j, TR[i].delay, i);
  1711.     }
  1712.     printf("\n};\n\n");
  1713. }
  1714.  
  1715. build_ffunc ()                    /* build fire functions */
  1716. {
  1717.     register int    i, j;
  1718.     register struct list_item *t, *q;
  1719.     register struct result *r;
  1720.  
  1721.     static char *eq_type[5] = {"ENQUEUE_I_TR(", "enqueue_e_tr(&",  "enqueue_d_tr(&",  "enqueue_n_tr(&",  "enqueue_b_tr(&"};
  1722.  
  1723.     for (i = 0; i < n_PL; i++) {
  1724.     printf ("#define REMOVE_M_PL%d\tPLACE[%d].H[PLACE[%d].cur_mrk].prob += clock - PLACE[%d].t_last;\\\n", i, i, i, i);
  1725.     printf ("\t\t\tPLACE[%d].t_last = clock;\\\n", i);
  1726.     printf ("\t\t\tif (!(--PLACE[%d].cur_mrk)) {\\\n", i);
  1727.     for (t = PL[i].input_ptr; t; t = t->next)
  1728.         printf("\t\t\t   if (!(TRANSITION[%d].ena_cnt++)) DEQUEUE_%c_TR(TRANSITION[%d]);\\\n", t->ind,
  1729.         (TR[t->ind].type == TTY_IMM) ? 'I' : 'X', t->ind);
  1730.     for (t = PL[i].inhib_ptr; t; t = t->next)
  1731.         printf("\t\t\t   if (!(--TRANSITION[%d].ena_cnt)) %sTRANSITION[%d]);\\\n", t->ind, eq_type[TR[t->ind].type],  t->ind);
  1732.     printf ("\t\t\t}\n");
  1733.  
  1734.     printf ("#define ADD_M_PL%d\tPLACE[%d].H[PLACE[%d].cur_mrk].prob += clock - PLACE[%d].t_last;\\\n", i, i, i, i);
  1735.     printf ("\t\t\tPLACE[%d].t_last = clock;\\\n", i);
  1736.     printf ("\t\t\tif (!(PLACE[%d].cur_mrk++)) {\\\n", i);
  1737.     for (t = PL[i].inhib_ptr; t; t = t->next)
  1738.         printf("\t\t\t   if (!(TRANSITION[%d].ena_cnt++)) DEQUEUE_%c_TR(TRANSITION[%d]);\\\n", t->ind,
  1739.         (TR[t->ind].type == TTY_IMM) ? 'I' : 'X', t->ind);
  1740.     for (t = PL[i].input_ptr; t; t = t->next)
  1741.         printf("\t\t\t   if (!(--TRANSITION[%d].ena_cnt)) %sTRANSITION[%d]);\\\n", t->ind, eq_type[TR[t->ind].type],  t->ind);
  1742.     printf ("\t\t\t}\\\n");
  1743.     printf ("\t\t\tif (PLACE[%d].cur_mrk >= PLACE[%d].max_mrk) add_H_space (&PLACE[%d])\n\n", i, i, i);
  1744.     }
  1745.  
  1746.     for (i = 0; i < n_TR; i++) {
  1747.     for (j = n_RS, r = RS; j--; r++)
  1748.         r->flg = 0;                /* default: assume result is not affected */
  1749.  
  1750.     printf("void fire_T%d()\n{\n", i);
  1751.     printf("    TRANSITION[%d].fire_cnt++;\n", i);
  1752.     for (t = TR[i].input_ptr; t; t = t->next){
  1753.         printf("    REMOVE_M_PL%d;\n", t->ind);
  1754.         for (q = PL[t->ind].result_ptr; q; q = q->next)
  1755.         RS[q->ind].flg = 1;        /* mark results that depend on this place */
  1756.     }
  1757.     for (t = TR[i].output_ptr; t; t = t->next) {
  1758.         printf("    ADD_M_PL%d;\n", t->ind);
  1759.         for (q = PL[t->ind].result_ptr; q; q = q->next)
  1760.         RS[q->ind].flg = 1;        /* mark results that depend on this place */
  1761.     }
  1762.  
  1763.     for (j = 0; j < n_RS; j++)
  1764.         if (RS[j].flg)
  1765.         printf("    rs_func%d();\n", j);
  1766.  
  1767.     if (TR[i].type != TTY_IMM) {
  1768.         printf("    if(!TRANSITION[%d].ena_cnt) {\n", i);
  1769.         printf("\tDEQUEUE_X_TR(TRANSITION[%d]);\n", i);
  1770.         printf("\t%sTRANSITION[%d]);\n", eq_type[TR[i].type], i);
  1771.         printf("    }\n");
  1772.     }
  1773.     printf("}\n\n");
  1774.     }
  1775.  
  1776.     for (i = 0; i < n_PL; i++)
  1777.     printf("#undef REMOVE_M_PL%d\n#undef ADD_M_PL%d\n", i, i);
  1778. }
  1779.  
  1780. build_param()                    /* dump the parameter structure */
  1781. {
  1782.     register int i, j, k, *ip, i_cnt, d_cnt;
  1783.     register struct parameter *p;
  1784.  
  1785.     printf("#define N_PARAMETERS %d\n\n", n_PR);
  1786.  
  1787.     if (!n_PR) {                /* no parameters, dump dummy to keep compiler happy */
  1788.     printf("struct parameter PARAMETER[1];\n");
  1789.     printf("double *d_param[1];\n");
  1790.     printf("unsigned short *i_param[1];\n");
  1791.     return;
  1792.     }
  1793.  
  1794.     printf("struct parameter PARAMETER[N_PARAMETERS] = {");
  1795.     i_cnt = 0;
  1796.     d_cnt = 0;
  1797.     for (i = n_PR, p =PR; i--; p++) {
  1798.     if (p->type) {
  1799.         printf("\n    {\"%s\", 1, %d, %d, %.10e}", p->name, p->used, d_cnt, p->value);
  1800.         d_cnt += p->used;
  1801.     } else {
  1802.         printf("\n    {\"%s\", 0, %d, %d, %.10e}", p->name, p->used, i_cnt, p->value);
  1803.         i_cnt += p->used;
  1804.     }
  1805.     if(i)
  1806.         printf (",");
  1807.     }
  1808.     printf("\n};\n");
  1809.  
  1810.     if(d_cnt) {
  1811.     printf("double *d_param[%d] = {\n    ", d_cnt);
  1812.     for (i = n_PR, p =PR, k = 0; i--; p++)
  1813.         if (p->type) {
  1814.         for (j = p->used, ip = p->ind; j--; ip++)
  1815.             printf ("&(TRANSITION[%d].delay)%s", *ip,
  1816.                 (--d_cnt) ? ((++k & 3) ? ", " : ",\n    ") : "};\n");
  1817.         }
  1818.     } else
  1819.     printf("double *d_param[1];\n");
  1820.  
  1821.     if(i_cnt) {
  1822.     printf("unsigned short *i_param[%d] = {\n    ", i_cnt);
  1823.     for (i = n_PR, p =PR, k = 0; i--; p++)
  1824.         if (!p->type) {
  1825.         for (j = p->used, ip = p->ind; j--; ip++)
  1826.             printf ("&(PLACE[%d].ini_mrk)%s", *ip,
  1827.                 (--i_cnt) ? ((++k & 3) ? ", " : ",\n    ") : "};\n");
  1828.         }
  1829.     } else
  1830.     printf("unsigned short *i_param[1];\n\n");
  1831. }
  1832.  
  1833.  
  1834. add_result (s, b)                    /* got a new result def */
  1835.     register char *s, *b;
  1836. {
  1837.     register int    i;
  1838.     register struct result *r;
  1839.  
  1840.     for (i = n_RS, r = RS; i--; r++)        /* see if result is allready defined */
  1841.     if (!strcmp(s, r->name)) {
  1842.         free(s);
  1843.         free(b);
  1844.         yyerror("Result multiply defined");
  1845.         return;
  1846.     }
  1847.  
  1848.     if (n_RS >= max_RS) {            /* need more space */
  1849.     max_RS += 50 + max_RS / 2;
  1850.     if (RS)
  1851.         RS = (struct result *) realloc(RS, sizeof(struct result) * max_RS);
  1852.     else
  1853.         RS = (struct result *) malloc(sizeof(struct result) * max_RS);
  1854.     }
  1855.  
  1856.     r = &RS[n_RS++];
  1857.     r->name = s;                /* set up default transition structure */
  1858.     r->body = b;
  1859.     r->type = result_type;
  1860. }
  1861.  
  1862. char *concat (s1, s2)
  1863.     char *s1, *s2;
  1864. {
  1865.     register char *s;
  1866.     s = (char *) malloc (6 + strlen(s1) + strlen(s2));
  1867.     strcpy(s, s1);
  1868.     strcat(s, s2);
  1869.     free(s1);
  1870.     free(s2);
  1871.     return s;
  1872. }
  1873.  
  1874. ini_result()                    /* prepare for a result definition */
  1875. {
  1876.     result_type = 0;
  1877. }
  1878.  
  1879. char *do_prob(d, s)
  1880.     char *s, *d;
  1881. {
  1882.     char *s1;
  1883.  
  1884.     if (result_type && result_type != 1)
  1885.     yyerror("Dimension mismatch");
  1886.     result_type = 1;
  1887.  
  1888.     s1 = (char *) malloc(strlen(s) + 50);
  1889.     sprintf(s1, "    if (%s) t %c= %s;\n", s, it_opr, d);
  1890.     free(s);
  1891.     free(d);
  1892.     return s1;
  1893. }
  1894.  
  1895. char *do_exp(d, s)
  1896.     char *s, *d;
  1897. {
  1898.     char *s1;
  1899.  
  1900.     if (result_type && result_type != 1)
  1901.     yyerror("Dimension mismatch");
  1902.     result_type = 1;
  1903.  
  1904.     s1 = (char *) malloc(strlen(s) + 50);
  1905.     sprintf(s1, "    t %c= %s * %s;\n", it_opr, d, s);
  1906.     free(s);
  1907.     free(d);
  1908.     return s1;
  1909. }
  1910.  
  1911. char *do_cexp(d, s, c)
  1912.     char *s, *c, *d;
  1913. {
  1914.     char *s1;
  1915.  
  1916.     if (result_type && result_type != 1)
  1917.     yyerror("Dimension mismatch");
  1918.     result_type = 1;
  1919.  
  1920.     s1 = (char *) malloc(strlen(s) + 50 + strlen(c));
  1921.     sprintf(s1, "    if (%s) t %c= %s * %s;\n", c, it_opr, d, s);
  1922.     free(s);
  1923.     free(c);
  1924.     free(d);
  1925.     return s1;
  1926. }
  1927.  
  1928. char *do_dwell(c, s)
  1929.     char *c, *s;
  1930. {
  1931.     char *s1;
  1932.     int  i;
  1933.  
  1934.     if (result_type && result_type != 2)
  1935.     yyerror("Dimension mismatch");
  1936.     result_type = 2;
  1937.  
  1938.     s1 = (char *) malloc (100);
  1939.     i = find_place(s) - PL;
  1940.  
  1941.                     /* Note: that 10^-60 prevents div by 0 and nothing else */
  1942.     sprintf(s1, "    t %c= %s * acc_dwt(&PLACE[%d]) / (1e-60 + FIRE_TO%d);\n", it_opr, c, i, i);
  1943.     free(c);
  1944.     return s1;
  1945. }
  1946.  
  1947. char *do_fire(c, s)
  1948.     char *c, *s;
  1949. {
  1950.     char *s1;
  1951.     int  i;
  1952.  
  1953.     if (result_type && result_type != 3)
  1954.     yyerror("Dimension mismatch");
  1955.     result_type = 3;
  1956.  
  1957.     s1 = (char *) malloc (100);
  1958.     i = find_transition(s) - TR;
  1959.     sprintf(s1, "    t %c= %s * TRANSITION[%d].fire_cnt;\n", it_opr, c, i);
  1960.     free(c);
  1961.     return s1;
  1962. }
  1963.  
  1964. char *get_val (d)
  1965.     double d;
  1966. {
  1967.     char *s;
  1968.     double rint();
  1969.  
  1970.     s = (char *) malloc(50);
  1971.     if (d == rint(d))
  1972.     sprintf(s, "%.1f", d);
  1973.     else
  1974.     sprintf(s, "%.10e", d);
  1975.  
  1976.     return s;
  1977. }
  1978.  
  1979. char *get_para(s)
  1980.     char *s;
  1981. {
  1982.     char *s1;
  1983.     s1 = (char *) malloc(50);
  1984.     sprintf(s1, "PARAMETER[%d].value", find_param(s) - PR);
  1985.     return s1;
  1986. }
  1987.  
  1988. char *get_place (s)
  1989.     char *s;
  1990. {
  1991.     register struct place *p = find_place(s);
  1992.     register struct list_item *t = (struct list_item *) malloc (sizeof (struct list_item));
  1993.  
  1994.     char *s1 = (char *) malloc (30);
  1995.     sprintf (s1, "PLACE[%d].cur_mrk", (int) (p - PL));
  1996.     t->ind = n_RS;
  1997.     t->next = p->result_ptr;
  1998.     p->result_ptr = t;
  1999.     return s1;
  2000. }
  2001.  
  2002. char *c_negate (s)
  2003.     char *s;
  2004. {
  2005.     char *s1 = (char *) malloc (strlen(s) + 5);
  2006.     sprintf (s1, "!(%s)", s);
  2007.     free (s);
  2008.     return s1;
  2009. }
  2010.  
  2011. char *do_paren (s)
  2012.     char *s;
  2013. {
  2014.     char *s1 = (char *) malloc (strlen(s) + 5);
  2015.     sprintf (s1, "(%s)", s);
  2016.     free (s);
  2017.     return s1;
  2018. }
  2019.  
  2020. char *do_and (s1, s2)
  2021.     char *s1, *s2;
  2022. {
  2023.     char *s = (char *) malloc (strlen(s1) + 10 + strlen(s2));
  2024.     sprintf (s, "(%s && %s)", s1, s2);
  2025.     free (s1);
  2026.     free (s2);
  2027.     return s;
  2028. }
  2029.  
  2030. char *do_or (s1, s2)
  2031.     char *s1, *s2;
  2032. {
  2033.     char *s = (char *) malloc (strlen(s1) + 10 + strlen(s2));
  2034.     sprintf (s, "(%s || %s)", s1, s2);
  2035.     free (s1);
  2036.     free (s2);
  2037.     return s;
  2038. }
  2039.  
  2040. char *do_cmp (s1, s2, d)
  2041.     char *s1, *s2;
  2042.     double d;
  2043. {
  2044.     char *s = (char *) malloc (strlen(s1) + 20 + strlen(s2));
  2045.     sprintf (s, "(%s %s %d)", s1, s2, (int) (d + 0.5));
  2046.     free (s1);
  2047.     free (s2);
  2048.     return s;
  2049. }
  2050.  
  2051. build_rslts ()                    /* build result functions */
  2052. {
  2053.     register struct result *r;
  2054.     register int i;
  2055.  
  2056.     printf("#define N_RESULTS %d\n\n", n_RS);
  2057.  
  2058.     if (n_RS < 1) {
  2059.     printf("struct result RESULT[1];\n\n");    /* dummy for compilier happiness */
  2060.     return;
  2061.     }
  2062.  
  2063.     for (i = n_RS; i--;)
  2064.     printf ("void rs_func%d();\n", i);
  2065.  
  2066.     printf("struct result RESULT[N_RESULTS] = {\n");
  2067.     for (i = 0,  r = RS; i < n_RS; r++, i++)
  2068.     printf ("    {\"%s\", %d, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, rs_func%d}%s",
  2069.         r->name, r->type - 1, i, (i + 1 >= n_RS) ? "\n};\n\n" : ",\n");
  2070.  
  2071.     for (i = 0,  r = RS; i < n_RS; r++, i++) {
  2072.     if (r->type == 1) {
  2073.         printf ("void rs_func%d()\n{\n    register double t = 0.0;\n%s", i, r->body);
  2074.         printf ("    RESULT[%d].acc += RESULT[%d].cur * (clock - RESULT[%d].t_last);\n", i, i, i);
  2075.         printf ("    RESULT[%d].cur = t;\n", i);
  2076.         printf ("    RESULT[%d].t_last = clock;\n}\n\n", i);
  2077.     } else if (r->type == 2) {
  2078.         printf ("void rs_func%d()\n{\n    register double t = 0.0;\n%s", i, r->body);
  2079.         printf ("    RESULT[%d].sum += t;\n", i);
  2080.         printf ("    RESULT[%d].sum_sq += t * t;\n}\n\n", i);
  2081.     } else if (r->type == 3) {
  2082.         printf ("void rs_func%d()\n{\n    register double t = 0.0;\n%s", i, r->body);
  2083.         printf ("    RESULT[%d].sum += t /= clock;\n", i);
  2084.         printf ("    RESULT[%d].sum_sq += t * t;\n}\n\n", i);
  2085.     }
  2086.     }
  2087. }
  2088. !E!O!F!
  2089. #
  2090. # type    sh /usru1/agn/gspn/../gs.shar   to unpack this archive.
  2091. #
  2092. echo extracting gs_pp.h...
  2093. cat >gs_pp.h <<'!E!O!F!'
  2094. /* definitions for the gs-preprocessor */
  2095.  
  2096. /* transition types */
  2097. #define TTY_IMM        0
  2098. #define TTY_EXP        1
  2099. #define    TTY_DET        2
  2100. #define TTY_NRM        3
  2101. #define TTY_BIM        4
  2102.  
  2103. struct list_item {
  2104.     unsigned short  ind;
  2105.     struct list_item *next;
  2106. };
  2107.  
  2108. struct place {                /* a place */
  2109.     char        *name;
  2110.     unsigned        defined:1;
  2111.     unsigned        mdef:1;
  2112.     unsigned short  marks;
  2113.     unsigned short  n_input;
  2114.     unsigned short  n_output;
  2115.  
  2116.     struct list_item *input_ptr;
  2117.     struct list_item *inhib_ptr;
  2118.     struct list_item *result_ptr;
  2119. };
  2120.  
  2121. struct transition {            /* a transition */
  2122.     char        *name;
  2123.     unsigned        type:3;
  2124.     unsigned        def:1;
  2125.     unsigned        ddef:1;
  2126.     double        delay;
  2127.     unsigned        depdef:1;
  2128.     int            depend;            /* dependency parameter */
  2129.  
  2130.     unsigned short  n_input;
  2131.     unsigned short  n_output;
  2132.     unsigned short  n_inhib;
  2133.  
  2134.     struct list_item *input_ptr;
  2135.     struct list_item *output_ptr;
  2136.     struct list_item *inhib_ptr;
  2137. };
  2138.  
  2139. struct parameter {                /* a parameter definition */
  2140.     char        *name;
  2141.     unsigned        defined:1;
  2142.     unsigned short  used, max_used;        /* # of places used in */
  2143.     unsigned        type:1;            /* 0: marking, 1: rate */
  2144.     
  2145.     int            *ind;            /* usage index */
  2146.     double        value;
  2147. };
  2148.  
  2149. struct result {
  2150.     char        *name;            /* name of result variable */
  2151.     char        *body;            /* function body */
  2152.     unsigned        flg:1;
  2153.     unsigned        type:2;            /* 0: undef, 1:dimensionless, 2:a time verage */
  2154. };
  2155.  
  2156. char *get_place(), *do_paren(), *do_or(), *do_cexp(), *concat(), *c_negate(),
  2157.      *do_prob(), *do_cmp(), *do_cmp(), *do_and(), *do_exp();
  2158.  
  2159. extern char    it_opr;                /* item (result) operator */
  2160. !E!O!F!
  2161. #
  2162. # type    sh /usru1/agn/gspn/../gs.shar   to unpack this archive.
  2163. #
  2164. echo extracting gs_pp_lex.l...
  2165. cat >gs_pp_lex.l <<'!E!O!F!'
  2166. /************************************************************************\
  2167. *                                                                        *
  2168. *  GS: A Generalized, stochastic petri net Simulator                     *
  2169. *      V0.01      March 1989      Andreas Nowatzyk (agn@unh.cs.cmu.edu)  *
  2170. *      Carnegie-Mellon Univerity, School of Computer Science             *
  2171. *      Schenley Park, Pittsburgh, PA 15213                               *
  2172. *                                                                        *
  2173. \************************************************************************/
  2174.  
  2175. %%
  2176. [ \n\t]*            ; /* ignore white space        */
  2177. "/*".*"*/"            ; /* skip comments (\n problem) */
  2178. ^"#".*\n            {if (2 != sscanf (&yytext[1],"%d%s", &yylineno, src_file))
  2179.                      yyerror ("malformed cpp-directive");
  2180.                 }
  2181.  
  2182. ^"%end"                {return END;}
  2183. rate[ \n\t]*"="            {return RATE;}
  2184. "#marks"[ \n\t]*"="        {return MARKS;}
  2185. dep[ \n\t]*"="            {return DEPEND;}
  2186. det|deterministic        {return DET;}
  2187. imm|immediate            {return IMM;}
  2188. exp|exponential            {return EXP;}
  2189. normal                {return NORM;}
  2190. bimodal                {return BIMOD;}
  2191. TRANS                {return TRANS;}
  2192. PLACE                {return PLACE;}
  2193. RESULT                {return RESULT;}
  2194. PARAM                {return PARAM;}
  2195. Prob                {return PROB;}
  2196. Expt                {return EXP;}
  2197. Dwell                {return DWT;}
  2198. Fire                {return FIRE;}
  2199.  
  2200. [A-Za-z_][A-Za-z0-9_]*        {yylval.SYM = (char *) malloc (yyleng + 1);
  2201.                  strncpy (yylval.SYM, yytext, yyleng);
  2202.                  yylval.SYM[yyleng] = 0;
  2203.                  return NAME;}
  2204.  
  2205. [-+.0-9edED]+            {if (1 != sscanf(yytext, "%lf", &(yylval.VALUE))) REJECT;
  2206.                  return VAL;}
  2207.  
  2208. "=="|"!="|">="|"<="|">"|"<"    {yylval.SYM = (char *) malloc (yyleng + 1);
  2209.                  strncpy (yylval.SYM, yytext, yyleng);
  2210.                  yylval.SYM[yyleng] = 0;
  2211.                  return REL_OP;}
  2212.  
  2213. ";"                {return TERM;}
  2214. ","                {return SEP;}
  2215. ":"                {return COL;}
  2216. "/"                {return COND;}
  2217. "-->"                {return NEXT;}
  2218. "!"                {return NOT;}
  2219. "{"                {return OP_BR;}
  2220. "}"                {return CL_BR;}
  2221. "("                {return OP_PAR;}
  2222. ")"                {return CL_PAR;}
  2223. "&&"                {return AND;}
  2224. "||"                {return OR;}
  2225. "#"                {return HASH;}
  2226. "+"                {return PLUS;}
  2227. "-"                {return MINUS;}
  2228.  
  2229. %%
  2230. !E!O!F!
  2231. #
  2232. # type    sh /usru1/agn/gspn/../gs.shar   to unpack this archive.
  2233. #
  2234. echo extracting gs_pp_par.y...
  2235. cat >gs_pp_par.y <<'!E!O!F!'
  2236. %{
  2237.  
  2238. /************************************************************************\
  2239. *                                                                        *
  2240. *  GS: A Generalized, stochastic petri net Simulator                     *
  2241. *      V0.01      March 1989      Andreas Nowatzyk (agn@unh.cs.cmu.edu)  *
  2242. *      Carnegie-Mellon Univerity, School of Computer Science             *
  2243. *      Schenley Park, Pittsburgh, PA 15213                               *
  2244. *                                                                        *
  2245. \************************************************************************/
  2246.  
  2247. /*
  2248.  *  Grammar of the GSPN-Simuator input format.
  2249.  *
  2250.  *  I know that this isn't compatible with GreatSPAN's files,
  2251.  *  but I want something that could be understood with an normal
  2252.  *  text editor as well as with a specialized graphic tool. A simple
  2253.  *  list of numbers isn't my style.
  2254.  *
  2255.  */
  2256.  
  2257. #include <strings.h>
  2258. #include <stdio.h>
  2259. #include "gs_pp.h"
  2260.  
  2261. char src_file[80] = "<stdin>", it_opr;
  2262.  
  2263. %}
  2264.  
  2265. %start gspn            /* Grammar entry         */
  2266.  
  2267. %union ytoken { char *SYM; double VALUE;}
  2268. %type <SYM> sum item marking logic_cond compare opt_val
  2269. %token <SYM> NAME REL_OP
  2270. %token <VALUE> VAL
  2271. %token END TERM SEP COL NEXT NOT RATE MARKS DEPEND DET IMM EXP TRANS PLACE RESULT PARAM
  2272. %token PROB EXP OP_BR CL_BR OP_PAR CL_PAR COND AND OR HASH PLUS MINUS BIMOD NORM DWT FIRE
  2273.  
  2274. %left OR
  2275. %left AND
  2276. %left NOT
  2277.  
  2278. %%
  2279.  
  2280. gspn        :    body END
  2281.         ;
  2282.  
  2283. body        :    statement
  2284.         |    body statement
  2285.         ;
  2286.  
  2287. statement   :    place TERM
  2288.         |    transition TERM
  2289.         |    parameter TERM
  2290.         |   result TERM
  2291.         |    error TERM
  2292.         ;
  2293.  
  2294.  
  2295. parameter   :    PARAM NAME VAL        {add_param($2, $3);}
  2296.         ;
  2297.  
  2298.  
  2299. place        :    PLACE NAME        {add_place($2);}
  2300.         pl_plist
  2301.         ;
  2302.  
  2303. pl_plist    :
  2304.         |    pl_params
  2305.         ;
  2306.  
  2307. pl_params   :    pl_param
  2308.         |    pl_params SEP pl_param
  2309.         ;
  2310.  
  2311. pl_param    :    MARKS VAL        {chg_marks($2);}
  2312.         |    MARKS NAME        {chg_p_marks($2);}
  2313.         ;
  2314.  
  2315.  
  2316. transition  :    TRANS NAME        {add_transition($2);}
  2317.         type COL from NEXT to
  2318.         ;
  2319.  
  2320. type        :    DET tr_plist        {set_type(TTY_DET);}
  2321.         |   IMM tr_plist        {set_type(TTY_IMM);}
  2322.         |    EXP tr_plist        {set_type(TTY_EXP);}
  2323.         |   BIMOD tr_plist        {set_type(TTY_BIM);}
  2324.         |   NORM tr_plist        {set_type(TTY_NRM);}
  2325.         ;
  2326.  
  2327. tr_plist    :
  2328.         |   tr_params
  2329.         ;
  2330.  
  2331. tr_params   :    tr_param
  2332.         |    tr_params SEP tr_param
  2333.         ;
  2334.  
  2335. tr_param    :    RATE VAL        {chg_rate($2);}
  2336.         |   RATE NAME        {chg_p_rate($2);}
  2337.         |    DEPEND VAL        {chg_depend($2);}
  2338.         ;
  2339.  
  2340. from        :
  2341.         |    from NAME        {add_input($2);}
  2342.         |    from NOT NAME        {add_inhib($3);}
  2343.         ;
  2344.  
  2345. to        :
  2346.         |    to NAME            {add_output($2);}
  2347.         ;
  2348.  
  2349.  
  2350. result        :    RESULT                        {ini_result();}
  2351.         NAME COL    sum                {add_result($3, $5);}
  2352.         ;
  2353.  
  2354. sum        :            {it_opr = '+';}     item        {$$ = $2;}
  2355.         |    sum PLUS    {it_opr = '+';}  item        {$$ = concat ($1, $4);}
  2356.         |    sum MINUS    {it_opr = '-';}  item        {$$ = concat ($1, $4);}
  2357.         ;
  2358.  
  2359. item        :    opt_val PROB OP_BR logic_cond CL_BR        {$$ = do_prob ($1, $4);}
  2360.         |   opt_val EXP OP_BR marking CL_BR            {$$ = do_exp  ($1, $4);}
  2361.         |   opt_val EXP OP_BR marking COND logic_cond CL_BR    {$$ = do_cexp ($1, $4, $6);}
  2362.         |   opt_val DWT OP_BR NAME CL_BR            {$$ = do_dwell  ($1, $4);}
  2363.         |   opt_val FIRE OP_BR NAME CL_BR            {$$ = do_fire  ($1, $4);}
  2364.         ;
  2365.  
  2366. opt_val        :                            {$$ = get_val(1.0);}
  2367.         |   VAL                        {$$ = get_val($1);}
  2368.         |   NAME                        {$$ = get_para($1);}
  2369.         ;
  2370.  
  2371. marking        :   HASH NAME                    {$$ = get_place ($2);}
  2372.         ;
  2373.  
  2374. logic_cond  :    compare
  2375.         |   NOT logic_cond                    {$$ = c_negate ($2);}
  2376.         |   OP_PAR logic_cond CL_PAR            {$$ = do_paren ($2);}
  2377.         |   logic_cond AND logic_cond            {$$ = do_and ($1, $3);}
  2378.         |   logic_cond OR logic_cond            {$$ = do_or ($1, $3);}
  2379.         ;
  2380.  
  2381. compare        :   marking REL_OP VAL                {$$ = do_cmp ($1, $2, $3);}
  2382.         ;
  2383.  
  2384. %%
  2385.  
  2386. #include "gs_pp_lex.c"
  2387. #include "gs_pp.c"
  2388. !E!O!F!
  2389. #
  2390. # type    sh /usru1/agn/gspn/../gs.shar   to unpack this archive.
  2391. #
  2392. echo extracting makefile...
  2393. cat >makefile <<'!E!O!F!'
  2394. OBJ = xrand.o gs_main.o
  2395. CFLAGS = -O
  2396. LIBS = -ll -lm
  2397. CC = cc
  2398.  
  2399. #
  2400. # The BIN directory will contain all files necessary to build an simulator
  2401. #
  2402. BIN = /usr/agn/bin
  2403. #
  2404. # To install the stuff do a 'make install'
  2405. #
  2406. # The installed files are:
  2407. #
  2408. #    gs_pp  : preprocessor to convert net-descriptions (*.n) files to an
  2409. #             include file (sim.h)
  2410. #    net2n  : converts GreatSPN *.net files to *.n files
  2411. #    def2n  : likewise, but deals with *.def files
  2412. #    GS.o   : precompiled simulator modules
  2413. #    gs.h   : include file to build the simulator
  2414. #    gs.c   : compiles into static simulator structures
  2415. #    mk_sim : a shell-script to put it all together
  2416. #
  2417.  
  2418. all:    gs_pp GS.o net2n def2n
  2419.  
  2420. net2n:    net2n.c
  2421.     $(CC) $(CFLAGS) -o net2n net2n.c
  2422.  
  2423. def2n:    def2n.c
  2424.     $(CC) $(CFLAGS) -o def2n def2n.c -ll
  2425.  
  2426. gs_pp:    gs_pp.c gs_pp.h gs_pp_lex.c gs_pp_par.c
  2427.     $(CC) $(CFLAGS) -o gs_pp gs_pp_par.c $(LIBS)
  2428.  
  2429. GS.o:    gs.h gs.c $(OBJ)
  2430.     ld -r -o GS.o $(OBJ) -lm
  2431.  
  2432. install:
  2433.     cp def2n net2n GS.o gs.c gs.h gs_pp $(BIN)
  2434.     sed 's+DISTR-DIR+$(BIN)+g' < mk_sim > $(BIN)/mk_sim
  2435.     chmod 755 $(BIN)/mk_sim
  2436.  
  2437. #
  2438. # This is used only for debugging gs
  2439. #
  2440. test:    sim.h gs.h gs_main.c xrand.o gs.c
  2441.     cc -o test -g gs.c gs_main.c xrand.o -lm
  2442.  
  2443. sim.h:    gs_pp q.n
  2444.     gs_pp < q.n > sim.h
  2445. !E!O!F!
  2446. #
  2447. # type    sh /usru1/agn/gspn/../gs.shar   to unpack this archive.
  2448. #
  2449. echo extracting mk_sim...
  2450. cat >mk_sim <<'!E!O!F!'
  2451. # C-shell please!
  2452.  
  2453. if ($1:e != "n") then
  2454.     set pn = $1.n
  2455.     def2n < $1.def > $pn
  2456.     net2n < $1.net >> $pn
  2457.     if ($status) then
  2458.     echo "Problem in $1.net encountered"
  2459.     exit (1)
  2460.     endif
  2461. else
  2462.     set pn = $1
  2463. endif
  2464. /lib/cpp $pn | gs_pp > sim.h
  2465. if ($status) then
  2466.     echo "Preprocessing unsuccessful"
  2467.     exit (1)
  2468. endif
  2469. cc -O -o $pn:r -I. DISTR-DIR/gs.c DISTR-DIR/GS.o
  2470. if($status) then
  2471.     echo "Ooops, something went wrong"
  2472. else
  2473.     rm sim.h
  2474. endif
  2475.  
  2476.  
  2477. !E!O!F!
  2478. #
  2479. # type    sh /usru1/agn/gspn/../gs.shar   to unpack this archive.
  2480. #
  2481. echo extracting net2n.c...
  2482. cat >net2n.c <<'!E!O!F!'
  2483. /************************************************************************\
  2484. *                                                                        *
  2485. *  GS: A Generalized, stochastic petri net Simulator                     *
  2486. *      V0.01      March 1989      Andreas Nowatzyk (agn@unh.cs.cmu.edu)  *
  2487. *      Carnegie-Mellon Univerity, School of Computer Science             *
  2488. *      Schenley Park, Pittsburgh, PA 15213                               *
  2489. *                                                                        *
  2490. \************************************************************************/
  2491.  
  2492. /* Converts GreatSPN's net-files into a more resonable format */
  2493.  
  2494. #include <stdio.h>
  2495.  
  2496. #define TTY_IMM        0            /* transition types            */
  2497. #define TTY_EXP        1
  2498. #define    TTY_DET        2
  2499.  
  2500. char    *trns_types[3] = {"imm", "exp", "det"};
  2501.  
  2502. /******************** Data structures ********************/
  2503.  
  2504. struct place {                    /* A place is... */
  2505.     char        *name;
  2506.     int            tokens;
  2507. };
  2508.  
  2509. struct place_list {                /* list of places */
  2510.     struct place    *pl;
  2511.     struct place_list    *next;
  2512. };
  2513.  
  2514. struct transition {                /* A transition is... */
  2515.     char        *name;
  2516.     unsigned char    type;
  2517.     double        rate;
  2518.     int            dep;            /* enabling dependency */
  2519.  
  2520.     struct place_list    *inpts;
  2521.     struct place_list    *outpts;
  2522.     struct place_list    *inhibs;
  2523. };
  2524.  
  2525. struct parameter {                /* parameters */
  2526.     char        *name;
  2527.     double        deflt;
  2528. };
  2529.  
  2530. /******************** Net storage ********************/
  2531.  
  2532. struct place        *PLACES;
  2533. int            n_PL;
  2534.  
  2535. struct transition    *TRANSITIONS;
  2536. int            n_TR;
  2537.  
  2538. struct parameter    *RATES, *MARKS;
  2539. int            n_RT, n_MK;
  2540.  
  2541.  
  2542. main(argc, argv)                /* boring stuff */
  2543.     int    argc;
  2544.     char *argv[];
  2545. {
  2546.      read_net();
  2547.      print_net();
  2548. }
  2549.  
  2550. read_net ()                    /* read a network */
  2551. {
  2552.     register int    i, j;
  2553.     int             n_GR, k, l, m;
  2554.     register struct place_list *t;
  2555.     char            buf[1024], tmp[1024];
  2556.  
  2557.     while (gets(buf))                /* skip preamble */
  2558.     if (buf[0] == '|' && buf[1] == 0)
  2559.         break;
  2560.  
  2561.     if (!gets(buf) || 5 != sscanf(buf, "%*s%d%d%d%d%d", &n_MK, &n_PL, &n_RT, &n_TR, &n_GR) ||
  2562.     n_MK < 0 || n_PL < 1 || n_RT < 0 || n_TR < 1 || n_GR < 0)
  2563.     err("Bogus parameters");
  2564.  
  2565.                         /* allocate storrage */
  2566.     if (n_MK) MARKS = (struct parameter *) malloc(n_MK * sizeof(struct parameter));
  2567.     if (n_RT) RATES = (struct parameter *) malloc(n_RT * sizeof(struct parameter));
  2568.     PLACES = (struct place *) malloc(n_PL * sizeof(struct place));
  2569.     TRANSITIONS = (struct transition *) malloc(n_TR * sizeof(struct transition));
  2570.  
  2571.     for (i = 0; i < n_MK; i++) {        /* read mark-parameters */
  2572.     if (!gets(buf)) err("Premature end of file");
  2573.     if (2 != sscanf(buf, "%s%lf", tmp, &(MARKS[i].deflt)))
  2574.         err("Param problem");
  2575.     strcpy(MARKS[i].name = (char *) malloc(strlen(tmp) + 1), tmp);
  2576.     }
  2577.  
  2578.     for (i = 0; i < n_PL; i++) {        /* read places */
  2579.     if (!gets(buf)) err("Premature end of file");
  2580.     if (2 != sscanf(buf, "%s%d", tmp, &(PLACES[i].tokens)))
  2581.         err("Place def problem");
  2582.     strcpy(PLACES[i].name = (char *) malloc(strlen(tmp) + 1), tmp);
  2583.     }
  2584.  
  2585.     for (i = 0; i < n_RT; i++) {        /* read rate-parameters */
  2586.     if (!gets(buf)) err("Premature end of file");
  2587.     if (2 != sscanf(buf, "%s%lf", tmp, &(RATES[i].deflt)))
  2588.         err("Param problem");
  2589.     strcpy(RATES[i].name = (char *) malloc(strlen(tmp) + 1), tmp);
  2590.     }
  2591.  
  2592.     for (i = 0; i < n_GR; i++)            /* skip groups */
  2593.     if (!gets(buf)) err("Premature end of file");
  2594.  
  2595.     for (i = 0; i < n_TR; i++) {/* read transitions */
  2596.     if (!gets(buf)) err("Premature end of file");
  2597.     if (5 != sscanf(buf, "%s%lf%d%d%d", tmp, &(TRANSITIONS[i].rate), &(TRANSITIONS[i].dep), &k, &l) || l < 1)
  2598.         err("Transition def problem");
  2599.  
  2600.     switch (k) {
  2601.     case 0:
  2602.         TRANSITIONS[i].type = TTY_EXP;
  2603.         break;
  2604.     case 1:
  2605.         TRANSITIONS[i].type = TTY_IMM;
  2606.         break;
  2607.     case 127:
  2608.         TRANSITIONS[i].type = TTY_DET;
  2609.         if (TRANSITIONS[i].rate < 1e-10)
  2610.         err("0-delay, deterministic transition");
  2611.         TRANSITIONS[i].rate = 1.0 / TRANSITIONS[i].rate;
  2612.         break;
  2613.     default:
  2614.         err("Unknown transition type");
  2615.     }
  2616.  
  2617.     strcpy(TRANSITIONS[i].name = (char *) malloc(strlen(tmp) + 1), tmp);
  2618.     TRANSITIONS[i].inpts = 0;
  2619.     TRANSITIONS[i].outpts = 0;
  2620.     TRANSITIONS[i].inhibs = 0;
  2621.  
  2622.     for (j = l; j--;) {            /* read inputs */
  2623.         if (!gets(buf)) err("Premature end of file");
  2624.         if (3 != sscanf(buf, "%d%d%d", &k, &l, &m) || !k || --l < 0 || l >= n_PL || m < 0)
  2625.         err("Transition input def problem");
  2626.         if(k < 0) k = -k;
  2627.  
  2628.         while (k--) {
  2629.             t = (struct place_list *) malloc (sizeof(struct place_list));
  2630.         t->pl = &PLACES[l];
  2631.         t->next = TRANSITIONS[i].inpts;
  2632.         TRANSITIONS[i].inpts = t;
  2633.         }
  2634.  
  2635.         while (m--)                /* skip geo-info */
  2636.         if (!gets(buf)) err("Premature end of file");
  2637.     }
  2638.  
  2639.     if (!gets(buf)) err("Premature end of file");
  2640.     if (1 != sscanf (buf, "%d", &k) || k < 1) err("TR output problem");
  2641.     for (j = k; j--;) {            /* read outputs */
  2642.         if (!gets(buf)) err("Premature end of file");
  2643.         if (3 != sscanf(buf, "%d%d%d", &k, &l, &m) || !k || --l < 0 || l >= n_PL || m < 0)
  2644.         err("Transition output def problem");
  2645.         if(k < 0) k = -k;
  2646.  
  2647.         while (k--) {
  2648.             t = (struct place_list *) malloc (sizeof(struct place_list));
  2649.         t->pl = &PLACES[l];
  2650.         t->next = TRANSITIONS[i].outpts;
  2651.         TRANSITIONS[i].outpts = t;
  2652.         }
  2653.  
  2654.         while (m--)                /* skip geo-info */
  2655.         if (!gets(buf)) err("Premature end of file");
  2656.     }
  2657.  
  2658.     if (!gets(buf)) err("Premature end of file");
  2659.     if (1 != sscanf (buf, "%d", &k) || k < 0) err("TR inhibt problem");
  2660.     for (j = k; j--;) {            /* read inhibits */
  2661.         if (!gets(buf)) err("Premature end of file");
  2662.         if (3 != sscanf(buf, "%d%d%d", &k, &l, &m) || !k || --l < 0 || l >= n_PL || m < 0)
  2663.         err("Transition inhibit def problem");
  2664.  
  2665.         if (k) {
  2666.             t = (struct place_list *) malloc (sizeof(struct place_list));
  2667.         t->pl = &PLACES[l];
  2668.         t->next = TRANSITIONS[i].inhibs;
  2669.         TRANSITIONS[i].inhibs = t;
  2670.         }
  2671.  
  2672.         while (m--)                /* skip geo-info */
  2673.         if (!gets(buf)) err("Premature end of file");
  2674.     }
  2675.     }
  2676. }
  2677.  
  2678. err(s)
  2679.    char *s;
  2680. {
  2681.     fprintf (stderr, "%s\n", s);
  2682.     exit(1);
  2683. }
  2684.  
  2685. print_net ()                    /* print the garbage */
  2686. {
  2687.     register int i, j;
  2688.     register struct place_list *t;
  2689.  
  2690.     for (i = 0; i < n_MK; i++)
  2691.     printf ("PARAM %s %.10e;\n", MARKS[i].name,  MARKS[i].deflt);
  2692.  
  2693.     for (i = 0; i < n_RT; i++)
  2694.     printf ("PARAM %s %.10e;\n", RATES[i].name,  RATES[i].deflt);
  2695.  
  2696.     for (i = 0; i < n_PL; i++) {
  2697.     j = PLACES[i].tokens;
  2698.     if (j < 0) {
  2699.         j = -1 - j;
  2700.         if (j >= n_MK)
  2701.         err ("Marking parameter problem");
  2702.         printf ("PLACE %s #marks= %s;\n", PLACES[i].name, MARKS[j].name);
  2703.     } else
  2704.         printf ("PLACE %s #marks= %d;\n", PLACES[i].name, j);
  2705.     }
  2706.  
  2707.     for (i = 0; i < n_TR; i++) {
  2708.     if (TRANSITIONS[i].rate < 0) {
  2709.         j = -0.5 - TRANSITIONS[i].rate;
  2710.         if (j >= n_RT)
  2711.         err ("Rate parameter problem");
  2712.         printf ("TRANS %s %s rate= %s, dep= %d : ", TRANSITIONS[i].name,
  2713.             trns_types[TRANSITIONS[i].type], RATES[j].name, TRANSITIONS[i].dep);
  2714.     } else
  2715.         printf ("TRANS %s %s rate= %e, dep= %d : ", TRANSITIONS[i].name,
  2716.             trns_types[TRANSITIONS[i].type], TRANSITIONS[i].rate, TRANSITIONS[i].dep);
  2717.  
  2718.     for (t = TRANSITIONS[i].inpts; t; t = t->next)
  2719.         printf ("%s ", t->pl->name);
  2720.  
  2721.     for (t = TRANSITIONS[i].inhibs; t; t = t->next)
  2722.         printf ("!%s ", t->pl->name);
  2723.  
  2724.     printf ("-->");
  2725.  
  2726.     for (t = TRANSITIONS[i].outpts; t; t = t->next)
  2727.         printf (" %s", t->pl->name);
  2728.  
  2729.     printf(";\n");
  2730.     }
  2731.     printf("#end\n");
  2732. }
  2733. !E!O!F!
  2734. #
  2735. # type    sh /usru1/agn/gspn/../gs.shar   to unpack this archive.
  2736. #
  2737. echo extracting xrand.c...
  2738. cat >xrand.c <<'!E!O!F!'
  2739. #include <math.h>
  2740.  
  2741. /* Random number generators:
  2742.  *
  2743.  *  rnd_init (unsigned seed) 
  2744.  *            : initializes the generator
  2745.  *
  2746.  *  rnd_i ()        : returns positive integers [0,0x7fffffff]
  2747.  *  rnd_u ()        : returns unsigned's        [0,0xffffffff]
  2748.  *  rnd_ri (long n)    : returns positive integers [0,n-1]
  2749.  *  rnd_01d ()        : returns doubles        [0.0,1.0)
  2750.  *              Note: ")" is no typo - rnd_01d will not return a 1.0,
  2751.  *                              but can return the next smaller FP number.
  2752.  *  rnd_ned (double lam): returns neg. exponential distributed doubles [0.0,+inf)
  2753.  *  rnd_nedi (double rt): same with lam = 1/rt - used to save divides
  2754.  *
  2755.  *  Algorithm M as describes in Knuth's "Art of Computer Programming", Vol 2. 1969
  2756.  *  is used with a linear congruential generator (to get a good uniform
  2757.  *  distribution) that is permuted with a Fibonacci additive congruential
  2758.  *  generator to get good independence.
  2759.  *
  2760.  *  Bit, byte, and word distributions were extensively tested and pass
  2761.  *  Chi-squared test near perfect scores (>7E8 numbers tested, Uniformity
  2762.  *  assumption holds with probability > 0.999)
  2763.  *
  2764.  *  Run-up tests for on 7E8 numbers confirm independence with
  2765.  *  probability > 0.97.
  2766.  *
  2767.  *  Plotting random points in 2d reveals no apparent structure.
  2768.  *
  2769.  *  Autocorrelation on sequences of 5E5 numbers (A(i) = SUM X(n)*X(n-i), i=1..512)
  2770.  *  results in no obvious structure (A(i) ~ const).
  2771.  *
  2772.  *  On a SUN 3/60, rnd_u() takes about 19.4 usec per call, which is about 44%
  2773.  *  slower than Berkeley's random() (13.5 usec/call).
  2774.  *
  2775.  *  Except for speed and memory requirements, this generator outperforms
  2776.  *  random() for all tests. (random() scored rather low on uniformity tests,
  2777.  *  while independence test differences were less dramatic).
  2778.  *
  2779.  *  Thanks to M.Mauldin, H.Walker, J.Saxe and M.Molloy for inspiration & help.
  2780.  *
  2781.  *  (c) Copyright 1988 by A. Nowatzyk
  2782.  *
  2783.  */
  2784.  
  2785. /* LC-parameter selection follows recommendations in 
  2786.  * "Handbook of Mathematical Functions" by Abramowitz & Stegun 10th, edi.
  2787.  */
  2788. #define LC_A 66049            /* = 251^2, ~= sqrt(2^32)            */
  2789. #define LC_C 3907864577            /* result of a long trial & error series    */
  2790.  
  2791. #define Xrnd(x) (x * LC_A + LC_C)   /* the LC polynomial            */
  2792.             
  2793. static unsigned long Fib[55];        /* will use X(n) = X(n-55) - X(n-24)    */
  2794. static int Fib_ind;            /* current index in circular buffer        */
  2795. static unsigned long Xrnd_var;        /* LCA - recurrence variable        */
  2796. static unsigned long auxtab[256];   /* temporal permutation table        */
  2797. static unsigned long prmtab[64] = { /* spatial permutation table        */
  2798.     0xffffffff, 0x00000000,  0x00000000,  0x00000000,  /* 3210 */
  2799.     0x0000ffff, 0x00ff0000,  0x00000000,  0xff000000,  /* 2310 */
  2800.     0xff0000ff, 0x0000ff00,  0x00000000,  0x00ff0000,  /* 3120 */
  2801.     0x00ff00ff, 0x00000000,  0xff00ff00,  0x00000000,  /* 1230 */
  2802.  
  2803.     0xffff0000, 0x000000ff,  0x00000000,  0x0000ff00,  /* 3201 */
  2804.     0x00000000, 0x00ff00ff,  0x00000000,  0xff00ff00,  /* 2301 */
  2805.     0xff000000, 0x00000000,  0x000000ff,  0x00ffff00,  /* 3102 */
  2806.     0x00000000, 0x00000000,  0x00000000,  0xffffffff,  /* 2103 */
  2807.  
  2808.     0xff00ff00, 0x00000000,  0x00ff00ff,  0x00000000,  /* 3012 */
  2809.     0x0000ff00, 0x00000000,  0x00ff0000,  0xff0000ff,  /* 2013 */
  2810.     0x00000000, 0x00000000,  0xffffffff,  0x00000000,  /* 1032 */
  2811.     0x00000000, 0x0000ff00,  0xffff0000,  0x000000ff,  /* 1023 */
  2812.  
  2813.     0x00000000, 0xffffffff,  0x00000000,  0x00000000,  /* 0321 */
  2814.     0x00ffff00, 0xff000000,  0x00000000,  0x000000ff,  /* 0213 */
  2815.     0x00000000, 0xff000000,  0x0000ffff,  0x00ff0000,  /* 0132 */
  2816.     0x00000000, 0xff00ff00,  0x00000000,  0x00ff00ff   /* 0123 */
  2817. };
  2818.  
  2819. union hack {                /* used to access doubles as unsigneds    */
  2820.     double d;
  2821.     unsigned long u[2];
  2822. };
  2823.  
  2824. static union hack man;            /* mantissa bit vector            */
  2825.  
  2826. rnd_init (seed)                /* modified: seed 0-31 use precomputed stuff */
  2827.     unsigned seed;
  2828. {
  2829.     register unsigned long u;
  2830.     register int i;
  2831.     double x, y;
  2832.     union hack t;
  2833.  
  2834.     static unsigned seed_tab[32] = {
  2835.         0xbdcc47e5, 0x54aea45d, 0xec0df859, 0xda84637b,
  2836.         0xc8c6cb4f, 0x35574b01, 0x28260b7d, 0x0d07fdbf,
  2837.         0x9faaeeb0, 0x613dd169, 0x5ce2d818, 0x85b9e706,
  2838.         0xab2469db, 0xda02b0dc, 0x45c60d6e, 0xffe49d10,
  2839.         0x7224fea3, 0xf9684fc9, 0xfc7ee074, 0x326ce92a,
  2840.         0x366d13b5, 0x17aaa731, 0xeb83a675, 0x7781cb32,
  2841.         0x4ec7c92d, 0x7f187521, 0x2cf346b4, 0xad13310f,
  2842.         0xb89cff2b, 0x12164de1, 0xa865168d, 0x32b56cdf  };
  2843.  
  2844.     if (seed < 32)
  2845.     u = seed_tab[seed];
  2846.     else
  2847.     u = seed ^ seed_tab[seed & 31];
  2848.  
  2849.     for (i = 55; i--;)            /* set up Fibonacci additive congruential    */
  2850.     Fib[i] = u = Xrnd(u);
  2851.  
  2852.     for (i = 256; i--;)
  2853.     auxtab[i] = u = Xrnd(u);
  2854.  
  2855.     Fib_ind = u % 55;            /* select a starting point            */
  2856.  
  2857.     Xrnd_var = u;
  2858.  
  2859.     if (sizeof(x) != 2 * sizeof(unsigned long)) {
  2860.     x = 0.0;
  2861.     y = 1.0;
  2862.     y /= x;                /*** intentional divide by 0: rnd_01d will
  2863.                      not work because a double doesn't fit
  2864.                      in 2 unsigned longs on your machine! ***/
  2865.     };
  2866.  
  2867.     x = 1.0;
  2868.     y = 0.5;
  2869.     do {                /* find largest fp-number < 2.0        */
  2870.     t.d = x;
  2871.     x += y;
  2872.     y *= 0.5;
  2873.     } while (x != t.d && x < 2.0);
  2874.  
  2875.     man.d = 1.0;
  2876.     man.u[0] ^= t.u[0];
  2877.     man.u[1] ^= t.u[1];            /* man is now 1 for each mantissa bit    */
  2878. }
  2879.  
  2880. long rnd_i ()
  2881. /*
  2882.  * returns a positive, uniformly distributed random number in [0,0x7fffffff]
  2883.  */
  2884.     register unsigned long i, j, *t = Fib;
  2885.  
  2886.     i = Fib_ind;
  2887.     j = t[i];                    /* = X(n-55) */
  2888.     j -= (i >= 24) ? t[i - 24] : t[i + 21]; /* = X(n-24) */
  2889.     t[i] = j;
  2890.     if (++i >= 55) i = 0;
  2891.     Fib_ind = i;
  2892.  
  2893.     t = &auxtab[(j >> 24) & 0xff];
  2894.     i = *t;
  2895.     Xrnd_var = *t = Xrnd(Xrnd_var);
  2896.     t = &prmtab[j & 0x3c];
  2897.  
  2898.     j =  *t++ & i;
  2899.     j |= *t++ & ((i << 24) | ((i >>  8) & 0x00ffffff));
  2900.     j |= *t++ & ((i << 16) | ((i >> 16) & 0x0000ffff));
  2901.     j |= *t   & ((i <<  8) | ((i >> 24) & 0x000000ff));
  2902.     
  2903.     return j & 0x7fffffff;
  2904. }
  2905.  
  2906. unsigned long rnd_u ()
  2907. /*
  2908.  * same as rnd_i, but gives full 32 bit range
  2909.  */
  2910.     register unsigned long i, j, *t = Fib;
  2911.  
  2912.     i = Fib_ind;
  2913.     j = t[i];                    /* = X(n-55) */
  2914.     j -= (i >= 24) ? t[i - 24] : t[i + 21]; /* = X(n-24) */
  2915.     t[i] = j;
  2916.     if (++i >= 55) i = 0;
  2917.     Fib_ind = i;
  2918.  
  2919.     t = &auxtab[(j >> 24) & 0xff];
  2920.     i = *t;
  2921.     Xrnd_var = *t = Xrnd(Xrnd_var);
  2922.     t = &prmtab[j & 0x3c];
  2923.  
  2924.     j =  *t++ & i;
  2925.     j |= *t++ & ((i << 24) | ((i >>  8) & 0x00ffffff));
  2926.     j |= *t++ & ((i << 16) | ((i >> 16) & 0x0000ffff));
  2927.     j |= *t   & ((i <<  8) | ((i >> 24) & 0x000000ff));
  2928.     
  2929.     return j;
  2930. }
  2931.  
  2932. long rnd_ri (rng)
  2933.     long rng;
  2934. /*
  2935.  * randint: Return a random integer in a given Range [0..rng-1]
  2936.  *          Note:  0 < rng
  2937.  */
  2938. {
  2939.     register unsigned long  r, a;
  2940.  
  2941.     do {
  2942.     r = rnd_i();
  2943.     a = (r / rng) + 1;
  2944.     a *= rng;
  2945.     } while (a >= 0x7fffffff);
  2946.     
  2947.     a--;
  2948.     return a - r;
  2949. }
  2950.  
  2951. double rnd_01d ()
  2952. /*
  2953.  * returns a uniformly distributed double in the range of [0..1)
  2954.  *         or  0.0 <= rnd_01d() < 1.0 to be precise
  2955.  *
  2956.  * Note: this code assumes that 2 'unsigned long's can hold a 'double'
  2957.  *       (works on SUN-3's, SUN-4's, MIPS, VAXen, IBM RT's)
  2958.  */
  2959. {
  2960.     union hack t;
  2961.  
  2962.     t.d = 1.0;
  2963.  
  2964.     t.u[0] |= rnd_u() & man.u[0];          /* munch in 1st part   */
  2965.     t.u[1] |= rnd_u() & man.u[1];          /* munch in 2nd part   */
  2966.  
  2967.     return t.d - 1.0;
  2968. }
  2969.  
  2970. double rnd_ned (lam)
  2971.     double lam;
  2972. /*
  2973.  * returns a neg. exponential distributed double in the range of [0..+infinity)
  2974.  *         or  0.0 <= rnd_neg() < +infinity to be precise
  2975.  *
  2976.  * Note: this code assumes that 2 'unsigned long's can hold a 'double'
  2977.  *       it also assumes that 'log()' behaves as advertised.
  2978.  *
  2979.  */
  2980. {
  2981.     union hack t;
  2982.  
  2983.     t.d = 1.0;
  2984.  
  2985.     t.u[0] |= rnd_u() & man.u[0];          /* munch in 1st part   */
  2986.     t.u[1] |= rnd_u() & man.u[1];          /* munch in 2nd part   */
  2987.  
  2988.     return -log(2.0 - t.d) / lam;
  2989. }
  2990.  
  2991. double rnd_nedi (lam)
  2992.     double lam;
  2993. /*
  2994.  * same as 'rnd_ned' called with 1/lam
  2995.  *
  2996.  * This is used to save a divide operation in some places
  2997.  *
  2998.  */
  2999. {
  3000.     union hack t;
  3001.  
  3002.     t.d = 1.0;
  3003.  
  3004.     t.u[0] |= rnd_u() & man.u[0];          /* munch in 1st part   */
  3005.     t.u[1] |= rnd_u() & man.u[1];          /* munch in 2nd part   */
  3006.  
  3007.     return -log(2.0 - t.d) * lam;
  3008. }
  3009. !E!O!F!
  3010. -- 
  3011.    --  Andreas Nowatzyk  (DC5ZV)
  3012.  
  3013.    Carnegie-Mellon University         agn@unh.cs.cmu.edu
  3014.    Computer Science Department       (412) 268-3617
  3015.  
  3016.