1 /*
2  *  This program is free software; you can redistribute it and/or modify
3  *  it under the terms of the GNU General Public License as published by
4  *  the Free Software Foundation; either version 2 of the License, or
5  *  (at your option) any later version.
6  *
7  *  This program is distributed in the hope that it will be useful,
8  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *  GNU General Public License for more details.
11  *
12  *  You should have received a copy of the GNU General Public License
13  *  along with this program; if not, write to the Free Software
14  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15  *
16  *  Authors : Benjamin GAUTHIER - 24 Mar 2004
17  *            Joseph BANINO
18  *            Olivier JACQUES
19  *            Richard GAYRAUD
20  *            From Hewlett Packard Company.
21  */
22 
23 #ifndef __STAT_H__
24 #define __STAT_H__
25 
26 
27 #define TIME_LENGTH 64
28 #define DEFAULT_FILE_NAME (char*)"dumpFile"
29 #define DEFAULT_EXTENSION (char*)".csv"
30 
31 #define MAX_CHAR_BUFFER_SIZE 1024
32 
33 #include <ctime>
34 #include <vector>
35 #include <string>
36 #include <sys/time.h>
37 #include <time.h>
38 #include <iostream>
39 #include <fstream>
40 #include <stdio.h>
41 
42 #ifdef HAVE_GSL
43 #include <gsl/gsl_rng.h>
44 #include <gsl/gsl_randist.h>
45 #include <gsl/gsl_cdf.h>
46 #endif
47 
48 #include "variables.hpp"
49 
50 using namespace std;
51 
52 /*
53 __________________________________________________________________________
54 
55               C S t a t    C L A S S
56 __________________________________________________________________________
57 */
58 
59 /**
60  * This class provides some means to compute and display statistics.
61  * This is a singleton class.
62  */
63 
64 class CStat
65 {
66 public:
67 
68     std::vector<int> error_codes;
69 
70     /*
71      * This struct is used for repartition table
72      * border max is the max value allow for this range
73      * nbInThisBorder is the counter of value in this range
74      */
75     typedef struct _T_dynamicalRepartition {
76         unsigned int  borderMax;
77         unsigned long nbInThisBorder;
78     } T_dynamicalRepartition;
79 
80     typedef struct _T_value_rtt {
81         double  date ;
82         int  rtd_no ;
83         double  rtt  ;
84     } T_value_rtt, *T_pValue_rtt ;
85 
86     /**
87      * Actions on counters
88      */
89     enum E_Action {
90         E_NO_ACTION,
91         E_CREATE_OUTGOING_CALL,
92         E_CREATE_INCOMING_CALL,
93         E_CALL_FAILED,
94         E_CALL_SUCCESSFULLY_ENDED,
95         E_RESET_C_COUNTERS,
96         E_RESET_PD_COUNTERS,
97         E_RESET_PL_COUNTERS,
98         E_ADD_CALL_DURATION,
99         E_ADD_RESPONSE_TIME_DURATION,
100         E_FAILED_CANNOT_SEND_MSG,
101         E_FAILED_MAX_UDP_RETRANS,
102         E_FAILED_TCP_CONNECT,
103         E_FAILED_TCP_CLOSED,
104         E_FAILED_UNEXPECTED_MSG,
105         E_FAILED_CALL_REJECTED,
106         E_FAILED_CMD_NOT_SENT,
107         E_FAILED_REGEXP_DOESNT_MATCH,
108         E_FAILED_REGEXP_SHOULDNT_MATCH,
109         E_FAILED_REGEXP_HDR_NOT_FOUND,
110         E_FAILED_OUTBOUND_CONGESTION,
111         E_FAILED_TIMEOUT_ON_RECV,
112         E_FAILED_TIMEOUT_ON_SEND,
113         E_OUT_OF_CALL_MSGS,
114         E_WATCHDOG_MAJOR,
115         E_WATCHDOG_MINOR,
116         E_DEAD_CALL_MSGS,
117         E_FATAL_ERRORS,
118         E_WARNING,
119         E_RETRANSMISSION,
120         E_AUTO_ANSWERED,
121         E_ADD_GENERIC_COUNTER
122     };
123     /**
124      * Counters management
125      */
126     enum E_CounterName {
127         // Per-Scenario Counters
128         // Cumulative counters
129         CPT_C_IncomingCallCreated,
130         CPT_C_OutgoingCallCreated,
131         CPT_C_SuccessfulCall,
132         CPT_C_FailedCall,
133         CPT_C_CurrentCall,
134         CPT_C_CurrentCallPeak,
135         CPT_C_CurrentCallPeakTime,
136         CPT_C_NbOfCallUsedForAverageCallLength,
137         CPT_C_AverageCallLength_Sum,
138         CPT_C_AverageCallLength_Squares,
139         CPT_C_FailedCallCannotSendMessage,
140         CPT_C_FailedCallMaxUdpRetrans,
141         CPT_C_FailedCallTcpConnect,
142         CPT_C_FailedCallTcpClosed,
143         CPT_C_FailedCallUnexpectedMessage,
144         CPT_C_FailedCallCallRejected,
145         CPT_C_FailedCallCmdNotSent,
146         CPT_C_FailedCallRegexpDoesntMatch,
147         CPT_C_FailedCallRegexpShouldntMatch,
148         CPT_C_FailedCallRegexpHdrNotFound,
149         CPT_C_FailedOutboundCongestion,
150         CPT_C_FailedTimeoutOnRecv,
151         CPT_C_FailedTimeoutOnSend,
152         CPT_C_Retransmissions,
153 
154         // Periodic Display counter
155         CPT_PD_IncomingCallCreated, // must be first (RESET_PD_COUNTER macro)
156         CPT_PD_OutgoingCallCreated,
157         CPT_PD_SuccessfulCall,
158         CPT_PD_FailedCall,
159         CPT_PD_CurrentCallPeak,
160         CPT_PD_CurrentCallPeakTime,
161         CPT_PD_NbOfCallUsedForAverageCallLength,
162         CPT_PD_AverageCallLength_Sum,
163         CPT_PD_AverageCallLength_Squares,
164         CPT_PD_NbOfCallUsedForAverageResponseTime,
165         CPT_PD_NbOfCallUsedForAverageResponseTime_2, // This must match or exceed MAX_RTD_INFO
166         CPT_PD_NbOfCallUsedForAverageResponseTime_3, // This must match or exceed MAX_RTD_INFO
167         CPT_PD_NbOfCallUsedForAverageResponseTime_4, // This must match or exceed MAX_RTD_INFO
168         CPT_PD_NbOfCallUsedForAverageResponseTime_5, // This must match or exceed MAX_RTD_INFO
169         CPT_PD_AverageResponseTime_Sum,
170         CPT_PD_AverageResponseTime_Sum_2,
171         CPT_PD_AverageResponseTime_Sum_3,
172         CPT_PD_AverageResponseTime_Sum_4,
173         CPT_PD_AverageResponseTime_Sum_5,
174         CPT_PD_AverageResponseTime_Squares,
175         CPT_PD_AverageResponseTime_Squares_2,
176         CPT_PD_AverageResponseTime_Squares_3,
177         CPT_PD_AverageResponseTime_Squares_4,
178         CPT_PD_AverageResponseTime_Squares_5,
179         CPT_PD_FailedCallCannotSendMessage,
180         CPT_PD_FailedCallMaxUdpRetrans,
181         CPT_PD_FailedCallTcpConnect,
182         CPT_PD_FailedCallTcpClosed,
183         CPT_PD_FailedCallUnexpectedMessage,
184         CPT_PD_FailedCallCallRejected,
185         CPT_PD_FailedCallCmdNotSent,
186         CPT_PD_FailedCallRegexpDoesntMatch,
187         CPT_PD_FailedCallRegexpShouldntMatch,
188         CPT_PD_FailedCallRegexpHdrNotFound,
189         CPT_PD_FailedOutboundCongestion,
190         CPT_PD_FailedTimeoutOnRecv,
191         CPT_PD_FailedTimeoutOnSend,
192         CPT_PD_Retransmissions,
193 
194         // Periodic logging counter
195         CPT_PL_IncomingCallCreated, // must be first (RESET_PL_COUNTER macro)
196         CPT_PL_OutgoingCallCreated,
197         CPT_PL_SuccessfulCall,
198         CPT_PL_FailedCall,
199         CPT_PL_CurrentCallPeak,
200         CPT_PL_CurrentCallPeakTime,
201         CPT_PL_NbOfCallUsedForAverageCallLength,
202         CPT_PL_AverageCallLength_Sum,
203         /* The squares let us compute the standard deviation. */
204         CPT_PL_AverageCallLength_Squares,
205         CPT_PL_NbOfCallUsedForAverageResponseTime,
206         CPT_PL_NbOfCallUsedForAverageResponseTime_2,
207         CPT_PL_NbOfCallUsedForAverageResponseTime_3,
208         CPT_PL_NbOfCallUsedForAverageResponseTime_4,
209         CPT_PL_NbOfCallUsedForAverageResponseTime_5,
210         CPT_PL_AverageResponseTime_Sum,
211         CPT_PL_AverageResponseTime_Sum_2,
212         CPT_PL_AverageResponseTime_Sum_3,
213         CPT_PL_AverageResponseTime_Sum_4,
214         CPT_PL_AverageResponseTime_Sum_5,
215         CPT_PL_AverageResponseTime_Squares,
216         CPT_PL_AverageResponseTime_Squares_2,
217         CPT_PL_AverageResponseTime_Squares_3,
218         CPT_PL_AverageResponseTime_Squares_4,
219         CPT_PL_AverageResponseTime_Squares_5,
220         CPT_PL_FailedCallCannotSendMessage,
221         CPT_PL_FailedCallMaxUdpRetrans,
222         CPT_PL_FailedCallTcpConnect,
223         CPT_PL_FailedCallTcpClosed,
224         CPT_PL_FailedCallUnexpectedMessage,
225         CPT_PL_FailedCallCallRejected,
226         CPT_PL_FailedCallCmdNotSent,
227         CPT_PL_FailedCallRegexpDoesntMatch,
228         CPT_PL_FailedCallRegexpShouldntMatch,
229         CPT_PL_FailedCallRegexpHdrNotFound,
230         CPT_PL_FailedOutboundCongestion,
231         CPT_PL_FailedTimeoutOnRecv,
232         CPT_PL_FailedTimeoutOnSend,
233         CPT_PL_Retransmissions,
234 
235         E_NB_COUNTER,
236 
237         // Global Counters
238         // Cumulative counters
239         CPT_G_C_OutOfCallMsgs,
240         CPT_G_C_DeadCallMsgs,
241         CPT_G_C_FatalErrors,
242         CPT_G_C_Warnings,
243         CPT_G_C_WatchdogMajor,
244         CPT_G_C_WatchdogMinor,
245         CPT_G_C_AutoAnswered,
246         // Periodic Display counter
247         CPT_G_PD_OutOfCallMsgs,
248         CPT_G_PD_DeadCallMsgs,
249         CPT_G_PD_FatalErrors,
250         CPT_G_PD_Warnings,
251         CPT_G_PD_WatchdogMajor,
252         CPT_G_PD_WatchdogMinor,
253         CPT_G_PD_AutoAnswered, // must be last (RESET_PD_COUNTER)
254 
255         // Periodic logging counter
256         CPT_G_PL_OutOfCallMsgs,
257         CPT_G_PL_DeadCallMsgs,
258         CPT_G_PL_FatalErrors,
259         CPT_G_PL_Warnings,
260         CPT_G_PL_WatchdogMajor,
261         CPT_G_PL_WatchdogMinor,
262         CPT_G_PL_AutoAnswered, // must be last (RESET_PL_COUNTER)
263 
264         E_NB_G_COUNTER
265     };
266 
267     /*
268     ** exported methods
269     */
270 
271     /**
272      * Constructor.
273      */
274     CStat ();
275 
276     /**
277      * Destructor.
278      */
279     ~CStat ();
280 
281 
282     /**
283      * Delete the single instance of the class.
284      *
285      * Only one instance of CStat exists in the component. This
286      * instance is deleted when the close method is called.
287      */
288     void close ();
289 
290     /**
291      * ComputeStat Methods are used to modify counter value
292      * It's the main interface to update counter
293      *
294      * @return 0 if the action is known
295      *        -1 else
296      */
297     int computeStat (E_Action P_action);
298     int computeStat (E_Action P_action, unsigned long P_value);
299     int computeStat (E_Action P_action, unsigned long P_value, int which);
300 
301     /* This works for global counters and does not require an instance. */
302     static int globalStat (E_Action P_action);
303 
304     /**
305      * ComputeRtt Methods are used to calculate the response time
306      */
307     void computeRtt ( unsigned long long P_start_time, unsigned long long P_stop_time, int which);
308 
309     /**
310      * GetStat Method is used to retrieve a counter value
311      *
312      * @return the counter value
313      **/
314     unsigned long long GetStat (E_CounterName P_counter);
315 
316     /* Get the current start time. */
317     void getStartTime(struct timeval *t);
318 
319     /**
320      * formatTime.
321      *
322      * This method converts a struct timeval parameter into a printable string
323      * in the format given in parameter.
324      *
325      * @param P_tv.
326      * @return a pointer on a static string containing formated time
327      */
328     static char* formatTime (struct timeval* P_tv, bool with_epoch = false);
329 
330     /**
331      * setRepartitionCallLength
332      * - set the unsigned int table passed in parameter as the repartition table
333      *   for call length. This is done by calling the initRepartition methode on
334      *   the M_CallLengthRepartition variable.
335      * - set the char* list of int (must be separeted with coma as the
336      *   repartition table for call length
337      *   This is done by calling the createIntegerTable to transform the char*
338      *   list into unsigned int list. Then the initRepartition methode is
339      *   call with the created unsigned int list and the M_CallLengthRepartition
340      *   variable
341      *
342      * setRepartitionResponseTime
343      *   Same than setRepartitionCallLength with the variable
344      *  M_ResponseTimeRepartition variableinstead of M_CallLengthRepartition
345      *  variable
346      */
347     void setRepartitionCallLength   (unsigned int* repartition, int nombre);
348     void setRepartitionCallLength   (char * liste);
349     void setRepartitionResponseTime (unsigned int* repartition, int nombre);
350     void setRepartitionResponseTime (char * liste);
351 
352     /* define the file name to use to dump statistic in file */
353     void setFileName(const char* name);
354     void setFileName(const char* name, const char* extension);
355     void initRtt(const char* name, const char* extension, unsigned long P_value);
356 
357     /**
358      * Display data periodically updated on screen.
359      */
360     void displayData (FILE *f);
361     void displayStat(FILE *f);
362     void displayRepartition(FILE *f);
363     void displayRtdRepartition (FILE *f, int which);
364 
365     /**
366      * Dump data periodically in the file M_FileName
367      */
368     void dumpData ();
369 
370     void dumpDataRtt ();
371 
372     /**
373      * initialize the class variable member
374      */
375     int init();
376 
377     /**
378      * computeDiffTimeInMs.
379      *
380      * This method calculates elaped time in ms
381      *
382      * @param tf = final date
383      * @param ti = initial date
384      *
385      * @return number of ms between the 2 dates
386      */
387     static long computeDiffTimeInMs (struct timeval* tf, struct timeval* ti);
388 
389     /**
390      * msToHHMMSS.
391      *
392      * This converts an unsigned long containing a number of ms
393      * into a string expressing the same value in format HH:MM:SS.
394      *
395      * @param P_ms.
396      *
397      * @return a pointer on a static string containing formated time
398      */
399     static char* msToHHMMSS (unsigned long P_ms);
400 
401     /**
402      * msToHHMMSSmm.
403      *
404      * This converts an unsigned long containing a number of ms
405      * into a string expressing the same value in format HH:MM:SS:mmm.
406      *
407      * @param P_ms.
408      *
409      * @return a pointer on a static string containing formated time
410      */
411     static char* msToHHMMSSus (unsigned long P_ms);
412 
413     /* Get a counter ID by name. */
414     int findCounter(const char *counter, bool alloc);
415     int findRtd(const char *name, bool start);
416     void validateRtds();
417     int nRtds();
418 
419 private:
420     unsigned long long        M_counters[E_NB_COUNTER];
421     static unsigned long long M_G_counters[E_NB_G_COUNTER - E_NB_COUNTER];
422 
423 #define GENERIC_C 0
424 #define GENERIC_PD 1
425 #define GENERIC_PL 2
426 #define GENERIC_TYPES 3
427     unsigned long long           *M_genericCounters;
428 
429     str_int_map                   M_genericMap;
430     int_str_map                   M_revGenericMap;
431     int_str_map                   M_genericDisplay;
432 
433     str_int_map                   rtd_started;
434     str_int_map                   rtd_stopped;
435 
436 #define RTD_COUNT 0
437 #define RTD_SUM 1
438 #define RTD_SUMSQ 2
439 #define RTD_TYPES 3
440     unsigned long long           *M_rtdInfo;
441     str_int_map                   M_rtdMap;
442     int_str_map                   M_revRtdMap;
443 
444     T_dynamicalRepartition** M_ResponseTimeRepartition;
445     T_dynamicalRepartition*  M_CallLengthRepartition;
446     int                      M_SizeOfResponseTimeRepartition;
447     int                      M_SizeOfCallLengthRepartition;
448     struct timeval           M_startTime;
449     struct timeval           M_pdStartTime;
450     struct timeval           M_plStartTime;
451 
452     bool                     M_headerAlreadyDisplayed;
453     char*                    M_fileName;
454     ofstream*                M_outputStream;
455 
456     bool                     M_headerAlreadyDisplayedRtt ;
457     char*                    M_fileNameRtt               ;
458     ofstream*                M_outputStreamRtt           ;
459     double                   M_time_ref                  ;
460 
461     T_pValue_rtt             M_dumpRespTime              ;
462     unsigned int             M_counterDumpRespTime       ;
463     unsigned long            M_report_freq_dumpRtt       ;
464 
465     /**
466      * initRepartition
467      * This methode is used to create the repartition table with a table of
468      * unsigned int the reparition is created like following, with Vi the given
469      * value in the table
470      * 0    <= x <  V1
471      * V1   <= x <  V2
472      *  ...
473      * Vn-1 <= x <  Vn
474      *         x >= Vn
475      * So the repartition table have the size n+1 if the given table has a size
476      * of n */
477     void  initRepartition(unsigned int* repartition, int nombre,
478                           T_dynamicalRepartition ** tabRepartition, int* nbTab);
479 
480     /**
481      * createIntegerTable
482      * this method try to create a table of unsigned int with the list of char*
483      * passed in parameters
484      * if it succed, it's return true (1)
485      * else it's return false (0)
486      */
487     int  createIntegerTable(char * P_listeStr,
488                             unsigned int ** listeInteger,
489                             int * sizeOfList);
490 
491     /**
492      * isWellFormed
493      * this method check if the char* passed in parameter in really a list of
494      * integer separated with comma.
495      * if yes, it's return true (1)
496      * else, it's return false (0)
497      */
498     int  isWellFormed(char * P_listeStr, int * nombre);
499 
500     /**
501      * updateRepartition
502      * The method looks for the place to set the value passed in parameter
503      * Once found, the associated counter is incremented
504      */
505     void  updateRepartition( T_dynamicalRepartition* tabRepart,
506                              int sizeOfTab,
507                              unsigned long value);
508 
509     /**
510      * resetRepartition
511      * Zeros out all repartition counters.
512      */
513     void  resetRepartition(T_dynamicalRepartition* P_tabReport,
514                            int P_sizeOfTab);
515     /**
516      * displayRepartition
517      * Display the repartition passed in parameter at the screen
518      */
519     void  displayRepartition(FILE *f,
520                              T_dynamicalRepartition * tabRepartition,
521                              int sizeOfTab);
522 
523     /**
524      * sRepartitionHeader
525      * return a string with the range description of the given repartition
526      */
527     char* sRepartitionHeader(T_dynamicalRepartition * tabRepartition,
528                              int sizeOfTab,
529                              const char* P_repartitionName);
530 
531     /**
532      * sRepartitionInfo
533      * return a string with the number of value in the differente range of the
534      * given repartition
535      */
536     char* sRepartitionInfo(T_dynamicalRepartition * tabRepartition,
537                            int sizeOfTab);
538 
539     /**
540      * UpdateAverageCounter
541      * This methode compute the real moyenne with the passed value on the given
542      * counter
543      */
544     void updateAverageCounter(E_CounterName P_SumCounter,
545                               E_CounterName P_NbOfCallUsed,
546                               E_CounterName P_Squares,
547                               unsigned long P_value);
548 
549     /**
550      * computeStdev
551      * This method computes the standard deviation using our recorded mean
552      * and recorded mean square.
553      */
554     double computeStdev(E_CounterName P_SumCounter,
555                         E_CounterName P_NbOfCallUsed,
556                         E_CounterName P_Squares);
557 
558     /**
559      * computeMean
560      * This method computes the recorded sum and count.
561      */
562     double computeMean(E_CounterName P_SumCounter,
563                        E_CounterName P_NbOfCallUsed);
564 
565     double computeRtdMean(int which, int type);
566     double computeRtdStdev(int which, int type);
567 
568     /**
569      * Effective C++
570      *
571      * To prevent public copy ctor usage: no implementation
572      */
573     CStat (const CStat&);
574 
575     /**
576      * Effective C++
577      *
578      * To prevent public operator= usage: no implementation
579      */
580     CStat& operator=(const CStat&);
581 };
582 
583 /**
584  * This abstract class provides the ability to sample from a distribution.
585  */
586 class CSample
587 {
588 public:
589     virtual double sample() = 0;
590     virtual int textDescr(char *s, int len) = 0;
591     virtual int timeDescr(char *s, int len) = 0;
592     virtual double cdfInv(double percentile) = 0;
593     virtual ~CSample();
594 private:
595 };
596 
597 /* Always return a fixed value for the sample. */
598 class CFixed : public CSample
599 {
600 public:
601     CFixed(double value);
602     double sample();
603     int textDescr(char *s, int len);
604     int timeDescr(char *s, int len);
605     double cdfInv(double percentile);
606 private:
607     double value;
608 };
609 
610 /* Return the default scenario duration. */
611 class CDefaultPause : public CSample
612 {
613 public:
614     CDefaultPause();
615     double sample();
616     int textDescr(char *s, int len);
617     int timeDescr(char *s, int len);
618     double cdfInv(double percentile);
619 private:
620 };
621 
622 /* Uniform distribution. */
623 class CUniform : public CSample
624 {
625 public:
626     CUniform(double min, double max);
627     double sample();
628     int textDescr(char *s, int len);
629     int timeDescr(char *s, int len);
630     double cdfInv(double percentile);
631 private:
632     double min, max;
633 };
634 
635 #ifdef HAVE_GSL
636 /* Normal distribution. */
637 class CNormal : public CSample
638 {
639 public:
640     CNormal(double mean, double stdev);
641     double sample();
642     int textDescr(char *s, int len);
643     int timeDescr(char *s, int len);
644     double cdfInv(double percentile);
645 protected:
646     double mean, stdev;
647     gsl_rng *rng;
648 };
649 
650 /* Lognormal distribution. */
651 class CLogNormal : public CNormal
652 {
653 public:
CLogNormal(double mean,double stdev)654     CLogNormal(double mean, double stdev) : CNormal(mean, stdev) {};
655     double sample();
656     int textDescr(char *s, int len);
657     int timeDescr(char *s, int len);
658     double cdfInv(double percentile);
659 };
660 
661 /* Exponential distribution. */
662 class CExponential : public CSample
663 {
664 public:
665     CExponential(double mean);
666     double sample();
667     int textDescr(char *s, int len);
668     int timeDescr(char *s, int len);
669     double cdfInv(double percentile);
670 private:
671     double mean;
672     gsl_rng *rng;
673 };
674 
675 /* Weibull distribution. */
676 class CWeibull : public CSample
677 {
678 public:
679     CWeibull(double lambda, double k);
680     double sample();
681     int textDescr(char *s, int len);
682     int timeDescr(char *s, int len);
683     double cdfInv(double percentile);
684 private:
685     double lambda, k;
686     gsl_rng *rng;
687 };
688 
689 /* Pareto distribution. */
690 class CPareto : public CSample
691 {
692 public:
693     CPareto(double k, double xsubm);
694     double sample();
695     int textDescr(char *s, int len);
696     int timeDescr(char *s, int len);
697     double cdfInv(double percentile);
698 protected:
699     double k, xsubm;
700     gsl_rng *rng;
701 };
702 
703 /* Generalized Pareto distribution. */
704 class CGPareto : public CSample
705 {
706 public:
707     CGPareto(double shape, double scale, double location);
708     double sample();
709     int textDescr(char *s, int len);
710     int timeDescr(char *s, int len);
711     double cdfInv(double percentile);
712 protected:
713     double shape, scale, location;
714     gsl_rng *rng;
715 };
716 
717 
718 /* Gamma distribution. */
719 class CGamma : public CSample
720 {
721 public:
722     CGamma(double k, double theta);
723     double sample();
724     int textDescr(char *s, int len);
725     int timeDescr(char *s, int len);
726     double cdfInv(double percentile);
727 protected:
728     double k, theta;
729     gsl_rng *rng;
730 };
731 
732 /* Negative Binomial distribution. */
733 class CNegBin : public CSample
734 {
735 public:
736     CNegBin(double p, double n);
737     double sample();
738     int textDescr(char *s, int len);
739     int timeDescr(char *s, int len);
740     double cdfInv(double percentile);
741 protected:
742     double p, n;
743     gsl_rng *rng;
744 };
745 #endif
746 
747 #endif // __STAT_H__
748