#!/bin/sh
# autopkgtest check: compute values of cdf, pdf, quantiles, and compare them
# to the ones that are outputted by R.
# (C) 2020 Pierre Gruet.
# Author: Pierre Gruet <pgt@debian.org>

set -e

SOURCEDIR=$(pwd)
WORKDIR=$(mktemp -d)
trap "rm -rf $WORKDIR" 0 INT QUIT ABRT PIPE TERM
cd $WORKDIR

#Create the R code that will output the pdf, cdf and quantiles values.
cat <<EOF > stat.r
#Beta
vec=c(dbeta(.9, 1.7, 1.2), pbeta(.9, 1.7, 1.2), qbeta(.95, 1.7, 1.2));
#binomial
vec=c(vec, dbinom(1., 23., .3), pbinom(1., 23., .3), qbinom(.95, 23., .3));
#Cauchy
vec=c(vec, dcauchy(1., 1.5, .3), pcauchy(1., 1.5, .3), qcauchy(.95, 1.5, .3));
#Chisq
vec=c(vec, dchisq(1., 5.), pchisq(1., 5.), qchisq(.95, 5.));
#Exp
vec=c(vec, dexp(1., 1./1.5), pexp(1., 1./1.5), qexp(.95, 1./1.5));
#F
vec=c(vec, df(1., 2., 5.), pf(1., 2., 5.), qf(.95, 2., 5.));
#Gamma
vec=c(vec, dgamma(1., shape=1.5, scale=.3), pgamma(1., shape=1.5, scale=.3), qgamma(.95, shape=1.5, scale=.3));
#Geometric
vec=c(vec, dgeom(1., .7), pgeom(1., .7), qgeom(.95, .7));
#Hypergeometric
vec=c(vec, dhyper(1., 8., 5., 4.), phyper(1., 8., 5., 4.), qhyper(.95, 8., 5., 4.));
#Logistic
vec=c(vec, dlogis(1., 1.5, .3), plogis(1., 1.5, .3), qlogis(.95, 1.5, .3));
#Lognormal
vec=c(vec, dlnorm(1., .5, .3), plnorm(1., .5, .3), qlnorm(.95, .5, .3));
#Negative binomial
vec=c(vec, dnbinom(41., 23., .3), pnbinom(41., 23., .3), qnbinom(.95, 23., .3));
#Noncentral beta
vec=c(vec, dbeta(.9, 1.7, 1.2, .8), pbeta(.9, 1.7, 1.2, .8), qbeta(.95, 1.7, 1.2, .8));
#Noncentral chisq
vec=c(vec, dchisq(1., 5., .8), pchisq(1., 5., .8), qchisq(.95, 5., .8));
#Noncentral F
vec=c(vec, df(1., 2., 5., 1.), pf(1., 2., 5., 1.), qf(.95, 2., 5., 1.));
#Noncentral Student
vec=c(vec, dt(1., 5., .8), pt(1., 5., .8), qt(.95, 5., .8));
#Normal
vec=c(vec, dnorm(1., .8, 1.1), pnorm(1., .8, 1.1), qnorm(.95, .8, 1.1));
#Poisson
vec=c(vec, dpois(1., .8), ppois(1., .8), qpois(.95, .8));
#Uniform
vec=c(vec, dunif(1., .2, 2.3), punif(1., .2, 2.3), qunif(.95, .2, 2.3));
#Weibull
vec=c(vec, dweibull(1., 1.5, .3), pweibull(1., 1.5, .3), qweibull(.95, 1.5, .3));

mat=matrix(vec, c(20, 3), byrow=T);
write.csv(mat, file="valR.csv", row.names=F);
EOF

# Create the Java program that will load the R file with reference values, call
# the functions of the library and check the computed values.
cat <<EOF > CompareOutputs.java
import java.io.*;
import java.lang.*;
import java.util.*;
import DistLib.beta;
import DistLib.binomial;
import DistLib.cauchy;
import DistLib.chisquare;
import DistLib.exponential;
import DistLib.f;
import DistLib.gamma;
import DistLib.geometric;
import DistLib.hypergeometric;
import DistLib.logistic;
import DistLib.lognormal;
import DistLib.negative_binomial;
import DistLib.noncentral_beta;
import DistLib.noncentral_chisquare;
import DistLib.noncentral_f;
import DistLib.noncentral_t;
import DistLib.normal;
import DistLib.poisson;
import DistLib.uniform;
import DistLib.weibull;

public class CompareOutputs
{
        public static void main(String[] args) throws IOException
        {
                BufferedReader fic = new BufferedReader(new FileReader("valR.csv"));
                StringTokenizer tok;
                boolean errorMet=false;
                double expected, got;
                
                fic.readLine(); //Header line.
                
                //for beta(a=1.7, b=1.2): pdf at 0.9, cdf at 0.9, quantile 95%.
                tok=new StringTokenizer(fic.readLine(), ",");
                expected=Double.parseDouble(tok.nextToken());
                got=beta.density(.9, 1.7, 1.2);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on beta pdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=beta.cumulative(.9, 1.7, 1.2);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on beta cdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=beta.quantile(.95, 1.7, 1.2);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on beta quantile: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                
                //for binomial(n=23, p=0.3): pdf at 1, cdf at 1, quantile 95%.
                tok=new StringTokenizer(fic.readLine(), ",");
                expected=Double.parseDouble(tok.nextToken());
                got=binomial.density(1., 23., .3);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on binomial pdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=binomial.cumulative(1., 23., .3);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on binomial cdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=binomial.quantile(.95, 23., .3);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on binomial quantile: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                
                //for cauchy(loc=1.5, scale=0.3): pdf at 1, cdf at 1, quantile 95%.
                tok=new StringTokenizer(fic.readLine(), ",");
                expected=Double.parseDouble(tok.nextToken());
                got=cauchy.density(1., 1.5, .3);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on Cauchy pdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=cauchy.cumulative(1., 1.5, .3);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on Cauchy cdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=cauchy.quantile(.95, 1.5, .3);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on Cauchy quantile: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                
                //for chisquare(df=5): pdf at 1, cdf at 1, quantile 95%.
                tok=new StringTokenizer(fic.readLine(), ",");
                expected=Double.parseDouble(tok.nextToken());
                got=chisquare.density(1., 5.);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on chisq pdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=chisquare.cumulative(1., 5.);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on chisq cdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=chisquare.quantile(.95, 5.);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on chisq quantile: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                
                //for exponential(scale=1.5): pdf at 1, cdf at 1, quantile 95%.
                tok=new StringTokenizer(fic.readLine(), ",");
                expected=Double.parseDouble(tok.nextToken());
                got=exponential.density(1., 1.5);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on exponential pdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=exponential.cumulative(1., 1.5);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on exponential cdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=exponential.quantile(.95, 1.5);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on exponential quantile: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                
                //for f(n1=2, n2=5): pdf at 1, cdf at 1, quantile 95%.
                tok=new StringTokenizer(fic.readLine(), ",");
                expected=Double.parseDouble(tok.nextToken());
                got=f.density(1., 2., 5.);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on f pdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=f.cumulative(1., 2., 5.);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on f cdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=f.quantile(.95, 2., 5.);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on f quantile: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                
                //for gamma(shape=1.5, scale=0.3): pdf at 1, cdf at 1, quantile 95%.
                tok=new StringTokenizer(fic.readLine(), ",");
                expected=Double.parseDouble(tok.nextToken());
                got=gamma.density(1., 1.5, .3);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on gamma pdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=gamma.cumulative(1., 1.5, .3);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on gamma cdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=gamma.quantile(.95, 1.5, .3);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on gamma quantile: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                
                //for geometric(0.7): pdf at 1, cdf at 1, quantile 95%.
                tok=new StringTokenizer(fic.readLine(), ",");
                expected=Double.parseDouble(tok.nextToken());
                got=geometric.density(1., .7);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on geometric pdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=geometric.cumulative(1., .7);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on geometric cdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=geometric.quantile(.95, .7);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on geometric quantile: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                
                //for hypergeometric(NR=8, NB=5, n=4): pdf at 1, cdf at 1, quantile 95%.
                tok=new StringTokenizer(fic.readLine(), ",");
                expected=Double.parseDouble(tok.nextToken());
                got=hypergeometric.density(1., 8., 5., 4.);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on hypergeometric pdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=hypergeometric.cumulative(1., 8., 5., 4.);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on hypergeometric cdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=hypergeometric.quantile(.95, 8., 5., 4.);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on hypergeometric quantile: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                
                //for logistic(loc=1.5, scale=0.3): pdf at 1, cdf at 1, quantile 95%.
                tok=new StringTokenizer(fic.readLine(), ",");
                expected=Double.parseDouble(tok.nextToken());
                got=logistic.density(1., 1.5, .3);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on logistic pdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=logistic.cumulative(1., 1.5, .3);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on logistic cdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=logistic.quantile(.95, 1.5, .3);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on logistic quantile: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                
                //for lognormal(logmean=0.5, logsd=0.3): pdf at 1, cdf at 1, quantile 95%.
                tok=new StringTokenizer(fic.readLine(), ",");
                expected=Double.parseDouble(tok.nextToken());
                got=lognormal.density(1., .5, .3);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on lognormal pdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=lognormal.cumulative(1., .5, .3);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on lognormal cdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=lognormal.quantile(.95, .5, .3);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on lognormal quantile: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                
                //for negative_binomial(n=23, p=0.3): pdf at 41, cdf at 41, quantile 95%.
                tok=new StringTokenizer(fic.readLine(), ",");
                expected=Double.parseDouble(tok.nextToken());
                got=negative_binomial.density(41., 23., .3);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on negative_binomial pdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=negative_binomial.cumulative(41., 23., .3);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on negative_binomial cdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=negative_binomial.quantile(.95, 23., .3);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on negative_binomial quantile: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                
                //for noncentral_beta(a=1.7, b=1.2, lambda=0.8): pdf at 0.9, cdf at 0.9.
                tok=new StringTokenizer(fic.readLine(), ",");
                expected=Double.parseDouble(tok.nextToken());
                got=noncentral_beta.density(.9, 1.7, 1.2, .8);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on noncentral_beta pdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=noncentral_beta.cumulative(.9, 1.7, 1.2, .8);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on noncentral_beta cdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                
                //for noncentral_chisquare(df=5, lambda=0.8): pdf at 1, cdf at 1, quantile 95%.
                tok=new StringTokenizer(fic.readLine(), ",");
                expected=Double.parseDouble(tok.nextToken());
                got=noncentral_chisquare.density(1., 5., .8);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on noncentral_chisq pdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=noncentral_chisquare.cumulative(1., 5., .8);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on noncentral_chisq cdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=noncentral_chisquare.quantile(.95, 5., .8);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on noncentral_chisq quantile: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                
                //for noncentral_f(n1=2, n2=5, ncp=1): cdf at 1.
                tok=new StringTokenizer(fic.readLine(), ",");
                tok.nextToken();//pdf computed by R, unused.
                
                expected=Double.parseDouble(tok.nextToken());
                got=noncentral_f.cumulative(1., 2., 5., 1.);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on noncentral_f cdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                
                //for noncentral_t(df=5, delta=0.8): cdf at 1.
                tok=new StringTokenizer(fic.readLine(), ",");
                tok.nextToken();//pdf computed by R, unused.
                
                expected=Double.parseDouble(tok.nextToken());
                got=noncentral_t.cumulative(1., 5., .8);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on noncentral_t cdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                
                //for normal(mu=0.8, sigma=1.1): pdf at 1, cdf at 1, quantile 95%.
                tok=new StringTokenizer(fic.readLine(), ",");
                expected=Double.parseDouble(tok.nextToken());
                got=normal.density(1., .8, 1.1);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on normal pdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=normal.cumulative(1., .8, 1.1);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on normal cdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=normal.quantile(.95, .8, 1.1);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on normal quantile: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                
                //for poisson(lambda=0.8): pdf at 1, cdf at 1, quantile 95%.
                tok=new StringTokenizer(fic.readLine(), ",");
                expected=Double.parseDouble(tok.nextToken());
                got=poisson.density(1., .8);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on poisson pdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=poisson.cumulative(1., .8);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on poisson cdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=poisson.quantile(.95, .8);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on poisson quantile: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                
                //for uniform(a=0.2, b=2.3): pdf at 1, cdf at 1, quantile 95%.
                tok=new StringTokenizer(fic.readLine(), ",");
                expected=Double.parseDouble(tok.nextToken());
                got=uniform.density(1., .2, 2.3);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on uniform pdf: expected " + expected + ", got " + got);         errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=uniform.cumulative(1., .2, 2.3);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on uniform cdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=uniform.quantile(.95, .2, 2.3);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on uniform quantile: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                
                //for weibull(shape=1.5, scale=0.3): pdf at 1, cdf at 1, quantile 95%.
                tok=new StringTokenizer(fic.readLine(), ",");
                expected=Double.parseDouble(tok.nextToken());
                got=weibull.density(1., 1.5, .3);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on weibull pdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=weibull.cumulative(1., 1.5, .3);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on weibull cdf: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                expected=Double.parseDouble(tok.nextToken());
                got=weibull.quantile(.95, 1.5, .3);
                if (Math.abs(expected-got)>1.E-6) {
                        System.out.println("Error on weibull quantile: expected " + expected + ", got " + got);
                        errorMet=true;
                }
                
                
                fic.close();
                
                if (errorMet)
                        System.exit(1);
                else
                        System.out.println("Tests pass.");
        }
}
EOF

R --slave --no-save < stat.r

export CLASSPATH=".:/usr/share/java/distlib.jar"
javac CompareOutputs.java
java CompareOutputs

