\subsubsection{Distribution subclasses}

The Distribution class defines many get and set methods which are not overridden in it's subclasses. Since these methods are simple the are only code reviewed. All distribution subclasses have been tested. Subclass testing is divided to hard coded distribution classes (BetaDistribution, BinomialDistribution, ContinuousUniformDistribution, DiscreteUniformDistribution, PoissonDistribution) and to testing of UserDefinedDistribution class. The UserDefinedDistribution class is tested with the DistributionFactory.

\textbf{Hard coded distributions, methods to be tested:}

All of these methods return Fortran code.

\begin{itemize}
\item getIntroduction - Returns the introduction of NAG library functions
\item getFreqCode - Returns the Fortran call for frequency function
\item getGenCode - Returns the Fortran call for generator function
\end{itemize}

\textbf{Strategy:}

An object is created for each class. The methods are called for each class. GetIntroduction does not take in any parameters and it can be considered static. Only thing to check from getIntroduction is that it does return valid Fortran code. Methods getFreqCode and getGenCode take a String array as a parameter. The array must be a certain length depending on the class. getFreqCode and getGenCode are called only with valid parameters. The validity of the Fortran code returned by the methods is checked by reviewing and compiling it.

Distribution subclasses, DistributionSkeleton and DistributionFactory have a tester class DistributionTester. The test can be run by calling a public method run().


\newpage
\textbf{Expected results:}

\textbf{BetaDistribution}

\begin{verbatim}
The distribution has 2 parameters

Testing introduction

EXTERNAL G01EEF
EXTERNAL G05FEF

Generator function:

ifail = 0
CALL G05FEF(Param1, Param2, SIZE(Result variable), Result variable, ifail)
IF (ifail /= 0) THEN
WRITE (*, *) 'Error when trying to generate random numbers from beta 
& distribution, parameters: a = ', Param1, 'b = ', Param2
STOP
END IF

Frequency function:

ifail = -1
CALL G01EEF(Point, Param1, Param2, 1.0_dp, temp_real, temp_real, Result variable, 
& ifail)
IF (ifail /= 0) THEN
WRITE (*, *) 'Error when trying to calculate frequency of the beta 
& distribution, parameters: a = ', Param1, 'b = ', Param2
STOP
END IF
\end{verbatim}


\textbf{BinomialDistribution}

\begin{verbatim}
The distribution has 2 parameters

Testing introduction

INTEGER G05EYF
EXTERNAL G05EYF
EXTERNAL G05EDF
EXTERNAL G01BJF

Generator function:

ifail = 0
ALLOCATE(binomial_reference(1 : NINT(20 + 20 * SQRT(Param1 * Param2 * 
& (1 - Param2)))))
CALL G05EDF(Param1, Param2, binomial_reference, SIZE(binomial_reference), ifail)
IF (ifail /= 0) THEN
WRITE (*, *) 'Error when trying to generate random numbers from binomial 
& distribution, parameters: n = ', Param1, ' p = ', Param2
STOP
END IF
DO k=1, SIZE(Result variable)
Result variable(k)=G05EYF(binomial_reference, SIZE(binomial_reference))
END DO

Frequency function:

ifail=0
CALL G01BJF(Param1, Param2, Point, temp_real, temp_real, Result variable, ifail)
IF (ifail /= 0) THEN
WRITE (*, *) 'Error when trying to calculate frequency of the binomial 
& distribution, parameters: n = ',Param1, 'p = ',Param2
STOP
END IF
\end{verbatim}


\textbf{ContinuousUniformDistribution}

\begin{verbatim}
The distribution has 2 parameters

Testing introduction

EXTERNAL G05FAF

Generator function:

CALL G05FAF(Param1, Param2, SIZE(Result variable), Result variable)

Frequency function:

IF (Point < Param1 .OR. Point > Param2) THEN
Result variable = 0
ELSE
Result variable = 1.0 / (Param2 - (Param1))
END IF
\end{verbatim}


\textbf{DiscreteUniformDistribution}

\begin{verbatim}
The distribution has 2 parameters

Testing introduction

INTEGER G05DYF
EXTERNAL G05DYF

Generator function:

DO k=1, SIZE(Result variable)
Result variable(k) = G05DYF(Param1, Param2)
END DO
\end{verbatim}
\newpage
\begin{verbatim}
Frequency function:

IF (Point < Param1 .OR. Point > Param2) THEN
Result variable = 0
ELSE
Result variable = 1.0 / (REAL(Param2) - (REAL(Param1)) + 1.0)
END IF
\end{verbatim}


\textbf{PoissonDistribution}

\begin{verbatim}
The distribution has 1 parameters

Introduction

EXTERNAL G01BKF
EXTERNAL G05ECF
INTEGER G05EYF
EXTERNAL G05EYF

Generator function:

ifail = 0
ALLOCATE(poisson_reference(1 : NINT(20 + 20 * SQRT(Param1))))
CALL G05ECF(Param1, poisson_reference, SIZE(poisson_reference), ifail)
IF (ifail /= 0) THEN
WRITE (*, *) 'Error when trying to generate random numbers from poisson 
& distribution, parameters: mu = ', Param1
STOP
END IF
DO k=1, SIZE(Result variable)
Result variable(k)=G05EYF(poisson_reference, SIZE(poisson_reference))
END DO

Frequency function:

ifail=0
IF (Param1 > 1.0D+6) THEN
CALL G01BKF( 1.0D+6, Point, temp_real, temp_real, Result variable, ifail)
ELSE
CALL G01BKF(Param1, Point, temp_real, temp_real, Result variable, ifail)
END IF
IF (ifail /= 0) THEN
WRITE (*, *) 'Error when trying to calculate frequency of the poisson 
& distribution, parameters: mu = ', Param1
STOP
END IF
\end{verbatim}

\newpage
\subsubsection{DistributionSkeleton}

The DistributionSkeleton only contains a constructor, set and get methods. These methods are simple, so they are not tested except by reading the source code.

\subsubsection{DistributionFactory}

The DistributionFactory has two functionalities. First one is its constructor, which reads a user-defined distribution file. The constructor creates a DistributionSkeleton object for each distribution defined in the file. The second functionality is returning of correct Distribution objects.

\textbf{Methods to be tested:}

\begin{itemize}
\item DistributionFactory - the constructor
\item getDistribution - returns a Distribution object
\end{itemize}

\textbf{Strategy:}

The getDistribution method is tested first. It's called with the names of hard coded distributions. The class name of returned objects is checked to be correct. The constructor is tested next. Multiple DistributionFactory objects are created with different user distribution files. After the creation of an object, the getDistribution method is called with the names of the user defined functions. Some files contain correct user defined distributions, while some hold incorrect ones. The UserDefinedDistribution class is tested at the same time. getFreqCode and getGenCode are called for UserDefinedDistribution objects.

\textbf{Expected results:}

A DistributionFactory object is expected to return correct hard coded distributions when called with correct parameters. The constructor is expected to accept valid user defined distributions and reject incorrect ones. getDistribution method is also expected to return correct user defined distributions. The UserDefinedDistribution objects are expected to return correct Fortran code.

Valid definitions, user defined distribution file: 'user1.txt'.

\begin{verbatim}
! user_alpha 2 real integer .true.
! user_BETA 2 real integer .true.
! user_GaMmA 2 real integer .true.
! USER_delta 2 real integer .true.
! UsEr_EtA 2 real integer .true.
! user_theta 2 REAL INTEGER .true.
! user_iota 2 ReAl InTeGeR .true.
! user_kappa 1 integer .true.
! user_lambda 3 real integer real .true.
! user_mu 2 real integer .false.
! user_nu 2 integer real .false.
! user_xhi 2 real integer .FALSE.
! user_tau 2 integer real .TRUE.
!         user_phi       2       real    integer       .true.
!user_sigma 2 integer real .true.
! user_omega 2 REAL INTEGER .TRUE.
\end{verbatim}

Expected results of the user defined distribution file: 'user1.txt'.

\begin{verbatim}
Testing ! user_alpha 2 real integer .true.

Call name is user_AlpHa
Generation code:
CALL user_alpha_gen(Param1, Param2, Result)

Frequency code:
CALL user_alpha_freq(Param1, Param2, Point, Result)


Testing ! user_BETA 2 real integer .true.

Call name is user_beta
Generation code:
CALL user_beta_gen(Param1, Param2, Result)

Frequency code:
CALL user_beta_freq(Param1, Param2, Point, Result)


Testing ! user_GaMmA 2 real integer .true.

Call name is user_GAMMA
Generation code:
CALL user_gamma_gen(Param1, Param2, Result)

Frequency code:
CALL user_gamma_freq(Param1, Param2, Point, Result)


Testing ! USER_delta 2 real integer .true.

Call name is user_delta
Generation code:
CALL user_delta_gen(Param1, Param2, Result)

Frequency code:
CALL user_delta_freq(Param1, Param2, Point, Result)


Testing ! UsEr_EtA 2 real interger .true.

Call name is user_ETA
Generation code:
CALL user_eta_gen(Param1, Param2, Result)

Frequency code:
CALL user_eta_freq(Param1, Param2, Point, Result)


Testing ! user_theta 2 REAL INTEGER .true.

Call name is user_TheTa
Generation code:
CALL user_theta_gen(Param1, Param2, Result)

Frequency code:
CALL user_theta_freq(Param1, Param2, Point, Result)


Testing ! user_iota 2 ReAl InTeGeR .true.

Call name is user_iota
Generation code:
CALL user_iota_gen(Param1, Param2, Result)

Frequency code:
CALL user_iota_freq(Param1, Param2, Point, Result)


Testing ! user_kappa 1 integer .true.

Call name is user_kappa
Generation code:
CALL user_kappa_gen(Param1, Result)

Frequency code:
CALL user_kappa_freq(Param1, Point, Result)


Testing ! user_lambda 3 real interger real .true.

Call name is user_lambda
Generation code:
CALL user_lambda_gen(Param1, Param2, Param3, Result)

Frequency code:
CALL user_lambda_freq(Param1, Param2, Param3, Point, Result)


Testing ! user_mu 2 real interger .false.

Call name is user_MU
Generation code:
Generator function was not found for MU


Testing ! user_nu 2 integer real .false.

Call name is user_Nu
Generation code:
Generator function was not found for Nu


Testing ! user_xhi 2 real integer .FALSE.

Call name is user_XhI
Generation code:
Generator function was not found for XhI


Testing ! user_tau 2 integer real .TRUE.

Call name is user_taU
Generation code:
CALL user_tau_gen(Param1, Param2, Result)

Frequency code:
CALL user_tau_freq(Param1, Param2, Point, Result)


Testing !         user_phi       2       real    integer       .true.

Call name is user_PHI
Generation code:
CALL user_phi_gen(Param1, Param2, Result)

Frequency code:
CALL user_phi_freq(Param1, Param2, Point, Result)


Testing !user_sigma 2 integer real .true.

Call name is user_SigMa
Generation code:
CALL user_sigma_gen(Param1, Param2, Result)

Frequency code:
CALL user_sigma_freq(Param1, Param2, Point, Result)


Testing ! user_omega 2 REAL INTEGER .TRUE.

Call name is user_omega
Generation code:
CALL user_omega_gen(Param1, Param2, Result)

Frequency code:
CALL user_omega_freq(Param1, Param2, Point, Result)
\end{verbatim}

