## Model Definition for Inverse Gaussian Distribution

```/*--------------------------------------------------------------

SAS Sample Library

Name: svrtigau.sas
Description: Example Program from SAS/ETS User's Guide,
The SEVERITY Procedure
Title: Model Definition for Inverse Gaussian Distribution
Product: SAS/ETS Software
Keys: fitting continuous distributions
PROC: SEVERITY
Notes: If you run this sample program without any modification, then
the Sasuser.Svrtdist library contains functions and subroutines
that are identical to those in the Sashelp.Svrtdist library.
Further, if you run this sample without any modification to the
names of functions and subroutines, then PROC FCMP writes
warnings of the following nature to the SAS log:
WARNING: Function <name> was defined in a previous package.
Function <name> as defined in the current program will
be used as default when the package is not specified.
You can ignore such warnings; they appear because the functions
defined in this sample are already defined in the input library
Sashelp.Svrtdist.

--------------------------------------------------------------*/
proc fcmp library=sashelp.svrtdist outlib=sasuser.svrtdist.models;
function IGAUSS_DESCRIPTION() \$32;
length model \$32;
model = "Inverse Gaussian Distribution";
return(model);
endsub;

function IGAUSS_PARMCOUNT();
return(2);
endsub;

function IGAUSS_LOGPDF(x, Theta, Alpha);
/* Theta : Scale */
/* Alpha : Shape */
if (x >= 2.220446E-16) then do; /* constant('MACEPS') */
z = x/Theta;
pi = 3.14159265358979323846; /* constant('PI') */
return (0.5 * (log(Alpha) - log(2 * pi) - 3 * log(z))
- Alpha*(z-1)**2/(2*z) - log(Theta));
end;
else
return (-180.218266); /* constant('LOGSMALL') */
endsub;
function IGAUSS_PDF(x, Theta, Alpha);
/* Theta : Scale */
/* Alpha : Shape */
if (x >= 2.220446E-16) then do; /* constant('MACEPS') */
z = x/Theta;
pi = 3.14159265358979323846; /* constant('PI') */
return (sqrt(1.0/(2 * pi * z**2 * (z/Alpha))) *
exp(-(Alpha/z)*((z-1)**2)/2) / Theta);
end;
else
return (0);
endsub;

function IGAUSS_CDF(x, Theta, Alpha);
/* Theta : Scale */
/* Alpha : Shape */

if (x >= 2.220446E-16) then do; /* constant('MACEPS') */
z = (x/Theta);
t = sqrt(Alpha/z);

t1 = CDF('NORMAL',((z-1)*t));
t2 = CDF('NORMAL',(-(z+1)*t));
if (t2 <= 2.220446E-16) then /* constant('MACEPS') */
return (t1);
else
return (t1 + exp(2*Alpha) * t2);
end;
else
return (0);
endsub;
function IGAUSS_LOGCDF(x, Theta, Alpha);
/* Theta : Scale */
/* Alpha : Shape */

cdf = IGAUSS_CDF(x, Theta, Alpha);
if (missing(cdf)) then
return (.);
if (cdf > 0) then
return (log(cdf));
else
return (-180.218266); /* constant('LOGSMALL') */
endsub;

function IGAUSS_LOGSDF(x, Theta, Alpha);
/* Theta : Scale */
/* Alpha : Shape */

cdf = IGAUSS_CDF(x, Theta, Alpha);
if (missing(cdf)) then
return (.);
if (cdf < 1) then
return (log1px(-cdf));
else
return (-180.218266); /* constant('LOGSMALL') */
endsub;
function IGAUSS_SDF(x, Theta, Alpha);
/* Theta : Scale */
/* Alpha : Shape */

cdf = IGAUSS_CDF(x, Theta, Alpha);
if (missing(cdf)) then
return (.);
return (1-cdf);
endsub;

subroutine IGAUSS_PARMINIT(dim, x[*], nx[*], F[*], Ftype, Theta, Alpha);
outargs Theta, Alpha;
array m[2] / nosymbols;

/* Use Method of Moments */
call svrtutil_rawmoments(dim, x, nx, 2, m);

if (missing(m[1])) then do;
Theta = .;
Alpha = .;
end;
else do;
Theta = m[1];

t1 = m[2] - m[1]**2;
if (t1 < 2.220446E-16) then /* constant('MACEPS') */
Alpha = 1;
else
Alpha = m[1]**2/t1;
end;
endsub;

function IGAUSS_QUANTILE(p, Theta, Alpha);
/* Theta : Scale */
/* Alpha : Shape */
Lambda = Alpha * Theta;
return (quantile('IGAUSS', p, Lambda, Theta));
endsub;

function IGAUSS_MEAN(x, Theta, Alpha);
return (Theta);
endsub;
quit;

```