changeset 13171:19b9f17d22af

Overhaul of statistical distribution functions Support class "single" 75% reduction in memory usage More Matlab compatibility for corner cases * betacdf.m, betainv.m, betapdf.m, betarnd.m, binocdf.m, binoinv.m, binopdf.m, binornd.m, cauchy_cdf.m, cauchy_inv.m, cauchy_pdf.m, cauchy_rnd.m, chi2cdf.m, chi2inv.m, chi2pdf.m, chi2rnd.m, discrete_cdf.m, discrete_inv.m, discrete_pdf.m, discrete_rnd.m, empirical_cdf.m, empirical_inv.m, empirical_pdf.m, empirical_rnd.m, expcdf.m, expinv.m, exppdf.m, exprnd.m, fcdf.m, finv.m, fpdf.m, frnd.m, gamcdf.m, gaminv.m, gampdf.m, gamrnd.m, geocdf.m, geoinv.m, geopdf.m, geornd.m, hygecdf.m, hygeinv.m, hygepdf.m, hygernd.m, kolmogorov_smirnov_cdf.m, laplace_cdf.m, laplace_inv.m, laplace_pdf.m, laplace_rnd.m, logistic_cdf.m, logistic_inv.m, logistic_pdf.m, logistic_rnd.m, logncdf.m, logninv.m, lognpdf.m, lognrnd.m, nbincdf.m, nbininv.m, nbinpdf.m, nbinrnd.m, normcdf.m, norminv.m, normpdf.m, normrnd.m, poisscdf.m, poissinv.m, poisspdf.m, poissrnd.m, stdnormal_cdf.m, stdnormal_inv.m, stdnormal_pdf.m, stdnormal_rnd.m, tcdf.m, tinv.m, tpdf.m, trnd.m, unidcdf.m, unidinv.m, unidpdf.m, unidrnd.m, unifcdf.m, unifinv.m, unifpdf.m, unifrnd.m, wblcdf.m, wblinv.m, wblpdf.m, wblrnd.m: Return "single" outputs for "single" inputs, Use logical indexing rather than find() for 75% memory savings, Add tests for all functions, Use consistent documentation across all functions, More Matlab compatibilitcy for corner cases.
author Rik <octave@nomad.inbox5.com>
date Tue, 20 Sep 2011 12:13:13 -0700
parents 078729410a0d
children 536c6a5ab705
files NEWS scripts/statistics/distributions/betacdf.m scripts/statistics/distributions/betainv.m scripts/statistics/distributions/betapdf.m scripts/statistics/distributions/betarnd.m scripts/statistics/distributions/binocdf.m scripts/statistics/distributions/binoinv.m scripts/statistics/distributions/binopdf.m scripts/statistics/distributions/binornd.m scripts/statistics/distributions/cauchy_cdf.m scripts/statistics/distributions/cauchy_inv.m scripts/statistics/distributions/cauchy_pdf.m scripts/statistics/distributions/cauchy_rnd.m scripts/statistics/distributions/chi2cdf.m scripts/statistics/distributions/chi2inv.m scripts/statistics/distributions/chi2pdf.m scripts/statistics/distributions/chi2rnd.m scripts/statistics/distributions/discrete_cdf.m scripts/statistics/distributions/discrete_inv.m scripts/statistics/distributions/discrete_pdf.m scripts/statistics/distributions/discrete_rnd.m scripts/statistics/distributions/empirical_cdf.m scripts/statistics/distributions/empirical_inv.m scripts/statistics/distributions/empirical_pdf.m scripts/statistics/distributions/empirical_rnd.m scripts/statistics/distributions/expcdf.m scripts/statistics/distributions/expinv.m scripts/statistics/distributions/exppdf.m scripts/statistics/distributions/exprnd.m scripts/statistics/distributions/fcdf.m scripts/statistics/distributions/finv.m scripts/statistics/distributions/fpdf.m scripts/statistics/distributions/frnd.m scripts/statistics/distributions/gamcdf.m scripts/statistics/distributions/gaminv.m scripts/statistics/distributions/gampdf.m scripts/statistics/distributions/gamrnd.m scripts/statistics/distributions/geocdf.m scripts/statistics/distributions/geoinv.m scripts/statistics/distributions/geopdf.m scripts/statistics/distributions/geornd.m scripts/statistics/distributions/hygecdf.m scripts/statistics/distributions/hygeinv.m scripts/statistics/distributions/hygepdf.m scripts/statistics/distributions/hygernd.m scripts/statistics/distributions/kolmogorov_smirnov_cdf.m scripts/statistics/distributions/laplace_cdf.m scripts/statistics/distributions/laplace_inv.m scripts/statistics/distributions/laplace_pdf.m scripts/statistics/distributions/laplace_rnd.m scripts/statistics/distributions/logistic_cdf.m scripts/statistics/distributions/logistic_inv.m scripts/statistics/distributions/logistic_pdf.m scripts/statistics/distributions/logistic_rnd.m scripts/statistics/distributions/logncdf.m scripts/statistics/distributions/logninv.m scripts/statistics/distributions/lognpdf.m scripts/statistics/distributions/lognrnd.m scripts/statistics/distributions/nbincdf.m scripts/statistics/distributions/nbininv.m scripts/statistics/distributions/nbinpdf.m scripts/statistics/distributions/nbinrnd.m scripts/statistics/distributions/normcdf.m scripts/statistics/distributions/norminv.m scripts/statistics/distributions/normpdf.m scripts/statistics/distributions/normrnd.m scripts/statistics/distributions/poisscdf.m scripts/statistics/distributions/poissinv.m scripts/statistics/distributions/poisspdf.m scripts/statistics/distributions/poissrnd.m scripts/statistics/distributions/stdnormal_cdf.m scripts/statistics/distributions/stdnormal_inv.m scripts/statistics/distributions/stdnormal_pdf.m scripts/statistics/distributions/stdnormal_rnd.m scripts/statistics/distributions/tcdf.m scripts/statistics/distributions/tinv.m scripts/statistics/distributions/tpdf.m scripts/statistics/distributions/trnd.m scripts/statistics/distributions/unidcdf.m scripts/statistics/distributions/unidinv.m scripts/statistics/distributions/unidpdf.m scripts/statistics/distributions/unidrnd.m scripts/statistics/distributions/unifcdf.m scripts/statistics/distributions/unifinv.m scripts/statistics/distributions/unifpdf.m scripts/statistics/distributions/unifrnd.m scripts/statistics/distributions/wblcdf.m scripts/statistics/distributions/wblinv.m scripts/statistics/distributions/wblpdf.m scripts/statistics/distributions/wblrnd.m
diffstat 90 files changed, 4799 insertions(+), 2272 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS
+++ b/NEWS
@@ -4,9 +4,27 @@
  ** The PCRE library is now required to build Octave.
 
  ** Octave now features a profiler, thanks to the work of Daniel Kraft
-    under the Google Summer of Code mentorship program. The manual has
+    under the Google Summer of Code mentorship program.  The manual has
     been updated to reflect this addition.
 
+ ** Overhaul of statistical distribution functions
+
+    Functions now return "single" outputs for inputs of class "single".
+
+    75% reduction in memory usage through use of logical indexing.
+
+    Random sample functions now use the same syntax as rand() and accept
+    a comma separated list of dimensions or a dimension vector.
+
+    Functions have been made Matlab-compatible with regard to special
+    cases (probability on boundaries, probabilities for values outside
+    distribution, etc.).  This may cause subtle changes to existing
+    scripts.
+
+    negative binomial function has been extended to real, non-integer inputs.
+    discrete_inv() now returns v(1) for 0 instead of NaN.
+    nbincdf() recoded to use closed form solution with betainc().
+
  ** strread, textscan, and textread have been completely revamped.
 
     They now support nearly all Matlab functionality including:
@@ -20,7 +38,7 @@
  ** Certain string functions have been modified for greater Matlab compatibility
     and for 15X greater performance when operating on cell array of strings.
 
-    deblank : Now requires character or cellstr input
+    deblank : Now requires character or cellstr input.
     strtrim : Now requires character or cellstr input.
               No longer trims nulls ("\0") from string for ML compatibility.
     strmatch: Follows documentation precisely and ignores trailing spaces
--- a/scripts/statistics/distributions/betacdf.m
+++ b/scripts/statistics/distributions/betacdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,9 +19,9 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} betacdf (@var{x}, @var{a}, @var{b})
-## For each element of @var{x}, returns the CDF at @var{x} of the beta
-## distribution with parameters @var{a} and @var{b}, i.e.,
-## PROB (beta (@var{a}, @var{b}) @leq{} @var{x}).
+## For each element of @var{x}, compute the cumulative distribution function
+## (CDF) at @var{x} of the Beta distribution with parameters @var{a} and
+## @var{b}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -32,33 +33,61 @@
     print_usage ();
   endif
 
-  if (!isscalar (a) || !isscalar(b))
+  if (!isscalar (a) || !isscalar (b))
     [retval, x, a, b] = common_size (x, a, b);
     if (retval > 0)
-      error ("betacdf: X, A and B must be of common size or scalar");
+      error ("betacdf: X, A, and B must be of common size or scalars");
     endif
   endif
 
-  sz = size(x);
-  cdf = zeros (sz);
+  if (iscomplex (x) || iscomplex (a) || iscomplex (b))
+    error ("betacdf: X, A, and B must not be complex");
+  endif
 
-  k = find (!(a > 0) | !(b > 0) | isnan (x));
-  if (any (k))
-    cdf (k) = NaN;
+  if (isa (x, "single") || isa (a, "single") || isa (b, "single"))
+    cdf = zeros (size (x), "single");
+  else
+    cdf = zeros (size (x));
   endif
 
-  k = find ((x >= 1) & (a > 0) & (b > 0));
-  if (any (k))
-    cdf (k) = 1;
-  endif
+  k = isnan (x) | !(a > 0) | !(b > 0);
+  cdf(k) = NaN;
+
+  k = (x >= 1) & (a > 0) & (b > 0);
+  cdf(k) = 1;
 
-  k = find ((x > 0) & (x < 1) & (a > 0) & (b > 0));
-  if (any (k))
-    if (isscalar (a) && isscalar(b))
-      cdf (k) = betainc (x(k), a, b);
-    else
-      cdf (k) = betainc (x(k), a(k), b(k));
-    endif
+  k = (x > 0) & (x < 1) & (a > 0) & (b > 0);
+  if (isscalar (a) && isscalar (b))
+    cdf(k) = betainc (x(k), a, b);
+  else
+    cdf(k) = betainc (x(k), a(k), b(k));
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 0.5 1 2];
+%! y = [0 0 0.75 1 1];
+%!assert(betacdf (x, ones(1,5), 2*ones(1,5)), y);
+%!assert(betacdf (x, 1, 2*ones(1,5)), y);
+%!assert(betacdf (x, ones(1,5), 2), y);
+%!assert(betacdf (x, [0 1 NaN 1 1], 2), [NaN 0 NaN 1 1]);
+%!assert(betacdf (x, 1, 2*[0 1 NaN 1 1]), [NaN 0 NaN 1 1]);
+%!assert(betacdf ([x(1:2) NaN x(4:5)], 1, 2), [y(1:2) NaN y(4:5)]);
+
+%% Test class of input preserved
+%!assert(betacdf ([x, NaN], 1, 2), [y, NaN]);
+%!assert(betacdf (single([x, NaN]), 1, 2), single([y, NaN]));
+%!assert(betacdf ([x, NaN], single(1), 2), single([y, NaN]));
+%!assert(betacdf ([x, NaN], 1, single(2)), single([y, NaN]));
+
+%% Test input validation
+%!error betacdf ()
+%!error betacdf (1)
+%!error betacdf (1,2)
+%!error betacdf (1,2,3,4)
+%!error betacdf (ones(3),ones(2),ones(2))
+%!error betacdf (ones(2),ones(3),ones(2))
+%!error betacdf (ones(2),ones(2),ones(3))
+
--- a/scripts/statistics/distributions/betainv.m
+++ b/scripts/statistics/distributions/betainv.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,7 +19,7 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} betainv (@var{x}, @var{a}, @var{b})
-## For each component of @var{x}, compute the quantile (the inverse of
+## For each element of @var{x}, compute the quantile (the inverse of
 ## the CDF) at @var{x} of the Beta distribution with parameters @var{a}
 ## and @var{b}.
 ## @end deftypefn
@@ -32,36 +33,39 @@
     print_usage ();
   endif
 
-  if (!isscalar (a) || !isscalar(b))
+  if (!isscalar (a) || !isscalar (b))
     [retval, x, a, b] = common_size (x, a, b);
     if (retval > 0)
-      error ("betainv: X, A and B must be of common size or scalars");
+      error ("betainv: X, A, and B must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  inv = zeros (sz);
-
-  k = find ((x < 0) | (x > 1) | !(a > 0) | !(b > 0) | isnan (x));
-  if (any (k))
-    inv (k) = NaN;
+  if (iscomplex (x) || iscomplex (a) || iscomplex (b))
+    error ("betainv: X, A, and B must not be complex");
   endif
 
-  k = find ((x == 1) & (a > 0) & (b > 0));
-  if (any (k))
-    inv (k) = 1;
+  if (isa (x, "single") || isa (a, "single") || isa (b, "single"))
+    inv = zeros (size (x), "single");
+  else
+    inv = zeros (size (x));
   endif
 
+  k = (x < 0) | (x > 1) | !(a > 0) | !(b > 0) | isnan (x);
+  inv(k) = NaN;
+
+  k = (x == 1) & (a > 0) & (b > 0);
+  inv(k) = 1;
+
   k = find ((x > 0) & (x < 1) & (a > 0) & (b > 0));
   if (any (k))
-    if (!isscalar(a) || !isscalar(b))
-      a = a (k);
-      b = b (k);
+    if (!isscalar (a) || !isscalar (b))
+      a = a(k);
+      b = b(k);
       y = a ./ (a + b);
     else
       y = a / (a + b) * ones (size (k));
     endif
-    x = x (k);
+    x = x(k);
 
     if (isa (y, "single"))
       myeps = eps ("single");
@@ -97,7 +101,36 @@
       y_old = y_new;
     endfor
 
-    inv (k) = y_new;
+    inv(k) = y_new;
   endif
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.75 1 2];
+%!assert(betainv (x, ones(1,5), 2*ones(1,5)), [NaN 0 0.5 1 NaN]);
+%!assert(betainv (x, 1, 2*ones(1,5)), [NaN 0 0.5 1 NaN]);
+%!assert(betainv (x, ones(1,5), 2), [NaN 0 0.5 1 NaN]);
+%!assert(betainv (x, [1 0 NaN 1 1], 2), [NaN NaN NaN 1 NaN]);
+%!assert(betainv (x, 1, 2*[1 0 NaN 1 1]), [NaN NaN NaN 1 NaN]);
+%!assert(betainv ([x(1:2) NaN x(4:5)], 1, 2), [NaN 0 NaN 1 NaN]);
+
+%% Test class of input preserved
+%!assert(betainv ([x, NaN], 1, 2), [NaN 0 0.5 1 NaN NaN]);
+%!assert(betainv (single([x, NaN]), 1, 2), single([NaN 0 0.5 1 NaN NaN]));
+%!assert(betainv ([x, NaN], single(1), 2), single([NaN 0 0.5 1 NaN NaN]));
+%!assert(betainv ([x, NaN], 1, single(2)), single([NaN 0 0.5 1 NaN NaN]));
+
+%% Test input validation
+%!error betainv ()
+%!error betainv (1)
+%!error betainv (1,2)
+%!error betainv (1,2,3,4)
+%!error betainv (ones(3),ones(2),ones(2))
+%!error betainv (ones(2),ones(3),ones(2))
+%!error betainv (ones(2),ones(2),ones(3))
+%!error betainv (i, 2, 2)
+%!error betainv (2, i, 2)
+%!error betainv (2, 2, i)
+
--- a/scripts/statistics/distributions/betapdf.m
+++ b/scripts/statistics/distributions/betapdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ## Copyright (C) 2010 Christos Dimitrakakis
 ##
@@ -19,8 +20,8 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} betapdf (@var{x}, @var{a}, @var{b})
-## For each element of @var{x}, returns the PDF at @var{x} of the beta
-## distribution with parameters @var{a} and @var{b}.
+## For each element of @var{x}, compute the probability density function (PDF)
+## at @var{x} of the Beta distribution with parameters @var{a} and @var{b}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>, CD <christos.dimitrakakis@gmail.com>
@@ -32,70 +33,98 @@
     print_usage ();
   endif
 
-  if (!isscalar (a) || !isscalar(b))
+  if (!isscalar (a) || !isscalar (b))
     [retval, x, a, b] = common_size (x, a, b);
     if (retval > 0)
-      error ("betapdf: X, A and B must be of common size or scalar");
+      error ("betapdf: X, A, and B must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  pdf = zeros (sz);
+  if (iscomplex (x) || iscomplex (a) || iscomplex (b))
+    error ("betapdf: X, A, and B must not be complex");
+  endif
 
-  k = find (!(a > 0) | !(b > 0) | isnan (x));
-  if (any (k))
-    pdf (k) = NaN;
+  if (isa (x, "single") || isa (a, "single") || isa (b, "single"));
+    pdf = zeros (size (x), "single");
+  else
+    pdf = zeros (size (x));
   endif
 
-  k = find ((x > 0) & (x < 1) & (a > 0) & (b > 0) & ((a != 1) | (b != 1)));
-  if (any (k))
-    if (isscalar(a) && isscalar(b))
-      pdf(k) = exp ((a - 1) .* log (x(k))
-                            + (b - 1) .* log (1 - x(k))
-                    + lgamma(a + b) - lgamma(a) - lgamma(b));
-    else
-      pdf(k) = exp ((a(k) - 1) .* log (x(k))
-                            + (b(k) - 1) .* log (1 - x(k))
-                    + lgamma(a(k) + b(k)) - lgamma(a(k)) - lgamma(b(k)));
-    endif
+  k = !(a > 0) | !(b > 0) | isnan (x);
+  pdf(k) = NaN;
+
+  k = (x > 0) & (x < 1) & (a > 0) & (b > 0) & ((a != 1) | (b != 1));
+  if (isscalar (a) && isscalar (b))
+    pdf(k) = exp ((a - 1) * log (x(k))
+                  + (b - 1) * log (1 - x(k))
+                  + lgamma (a + b) - lgamma (a) - lgamma (b));
+  else
+    pdf(k) = exp ((a(k) - 1) .* log (x(k))
+                  + (b(k) - 1) .* log (1 - x(k))
+                  + lgamma (a(k) + b(k)) - lgamma (a(k)) - lgamma (b(k)));
   endif
 
   ## Most important special cases when the density is finite.
-  k = find ((x == 0) & (a == 1) & (b > 0) & (b != 1));
-  if (any (k))
-    if (isscalar(a) && isscalar(b))
-      pdf(k) = exp(lgamma(a + b) - lgamma(a) - lgamma(b));
-    else
-      pdf(k) = exp(lgamma(a(k) + b(k)) - lgamma(a(k)) - lgamma(b(k)));
-    endif
+  k = (x == 0) & (a == 1) & (b > 0) & (b != 1);
+  if (isscalar (a) && isscalar (b))
+    pdf(k) = exp (lgamma (a + b) - lgamma (a) - lgamma (b));
+  else
+    pdf(k) = exp (lgamma (a(k) + b(k)) - lgamma (a(k)) - lgamma (b(k)));
   endif
 
-  k = find ((x == 1) & (b == 1) & (a > 0) & (a != 1));
-  if (any (k))
-    if (isscalar(a) && isscalar(b))
-      pdf(k) = exp(lgamma(a + b) - lgamma(a) - lgamma(b));
-    else
-      pdf(k) = exp(lgamma(a(k) + b(k)) - lgamma(a(k)) - lgamma(b(k)));
-    endif
+  k = (x == 1) & (b == 1) & (a > 0) & (a != 1);
+  if (isscalar (a) && isscalar (b))
+    pdf(k) = exp (lgamma (a + b) - lgamma (a) - lgamma (b));
+  else
+    pdf(k) = exp (lgamma (a(k) + b(k)) - lgamma (a(k)) - lgamma (b(k)));
   endif
 
-  k = find ((x >= 0) & (x <= 1) & (a == 1) & (b == 1));
-  if (any (k))
-    pdf(k) = 1;
-  endif
+  k = (x >= 0) & (x <= 1) & (a == 1) & (b == 1);
+  pdf(k) = 1;
 
   ## Other special case when the density at the boundary is infinite.
-  k = find ((x == 0) & (a < 1));
-  if (any (k))
-    pdf(k) = Inf;
-  endif
+  k = (x == 0) & (a < 1);
+  pdf(k) = Inf;
 
-  k = find ((x == 1) & (b < 1));
-  if (any (k))
-    pdf(k) = Inf;
-  endif
+  k = (x == 1) & (b < 1);
+  pdf(k) = Inf;
 
 endfunction
 
-%% Test large values for betapdf
+
+%!shared x,y
+%! x = [-1 0 0.5 1 2];
+%! y = [0 2 1 0 0];
+%!assert(betapdf (x, ones(1,5), 2*ones(1,5)), y);
+%!assert(betapdf (x, 1, 2*ones(1,5)), y);
+%!assert(betapdf (x, ones(1,5), 2), y);
+%!assert(betapdf (x, [0 NaN 1 1 1], 2), [NaN NaN y(3:5)]);
+%!assert(betapdf (x, 1, 2*[0 NaN 1 1 1]), [NaN NaN y(3:5)]);
+%!assert(betapdf ([x, NaN], 1, 2), [y, NaN]);
+
+%% Test class of input preserved
+%!assert(betapdf (single([x, NaN]), 1, 2), single([y, NaN]));
+%!assert(betapdf ([x, NaN], single(1), 2), single([y, NaN]));
+%!assert(betapdf ([x, NaN], 1, single(2)), single([y, NaN]));
+
+%% Beta (1/2,1/2) == arcsine distribution
+%!test
+%! x = rand (10,1);
+%! y = 1./(pi * sqrt (x.*(1-x)));
+%! assert(betapdf (x, 1/2, 1/2), y, 50*eps);
+
+%% Test large input values to betapdf
 %!assert (betapdf(0.5, 1000, 1000), 35.678, 1e-3)
+
+%% Test input validation
+%!error betapdf ()
+%!error betapdf (1)
+%!error betapdf (1,2)
+%!error betapdf (1,2,3,4)
+%!error betapdf (ones(3),ones(2),ones(2))
+%!error betapdf (ones(2),ones(3),ones(2))
+%!error betapdf (ones(2),ones(2),ones(3))
+%!error betapdf (i, 2, 2)
+%!error betapdf (2, i, 2)
+%!error betapdf (2, 2, i)
+
--- a/scripts/statistics/distributions/betarnd.m
+++ b/scripts/statistics/distributions/betarnd.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,83 +18,120 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} betarnd (@var{a}, @var{b}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} betarnd (@var{a}, @var{b}, @var{sz})
-## Return an @var{r} by @var{c} or @code{size (@var{sz})} matrix of
-## random samples from the Beta distribution with parameters @var{a} and
-## @var{b}.  Both @var{a} and @var{b} must be scalar or of size @var{r}
-##  by @var{c}.
+## @deftypefn  {Function File} {} betarnd (@var{a}, @var{b})
+## @deftypefnx {Function File} {} betarnd (@var{a}, @var{b}, @var{r})
+## @deftypefnx {Function File} {} betarnd (@var{a}, @var{b}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} betarnd (@var{a}, @var{b}, [@var{sz}])
+## Return a matrix of random samples from the Beta distribution with parameters
+## @var{a} and @var{b}.
 ##
-## If @var{r} and @var{c} are omitted, the size of the result matrix is
-## the common size of @var{a} and @var{b}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the common size of
+## @var{a} and @var{b}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the Beta distribution
 
-function rnd = betarnd (a, b, r, c)
+function rnd = betarnd (a, b, varargin)
 
-  if (nargin > 1)
-    if (!isscalar(a) || !isscalar(b))
-      [retval, a, b] = common_size (a, b);
-      if (retval > 0)
-        error ("betarnd: A and B must be of common size or scalar");
-      endif
+  if (nargin < 2)
+    print_usage ();
+  endif
+
+  if (!isscalar (a) || !isscalar (b))
+    [retval, a, b] = common_size (a, b);
+    if (retval > 0)
+      error ("betarnd: A and B must be of common size or scalars");
     endif
   endif
 
-  if (nargin == 4)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("betarnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("betarnd: C must be a positive integer");
-    endif
-    sz = [r, c];
+  if (iscomplex (a) || iscomplex (b))
+    error ("betarnd: A and B must not be complex");
+  endif
 
-    if (any (size (a) != 1)
-        && (length (size (a)) != length (sz) || any (size (a) != sz)))
-      error ("betarnd: A and B must be scalar or of size [R,C]");
-    endif
+  if (nargin == 2)
+    sz = size (a);
   elseif (nargin == 3)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
     else
-      error ("betarnd: R must be a positive integer or vector");
+      error ("betarnd: dimension vector must be row vector of non-negative integers");
     endif
-
-    if (any (size (a) != 1)
-        && (length (size (a)) != length (sz) || any (size (a) != sz)))
-      error ("betarnd: A and B must be scalar or of size SZ");
+  elseif (nargin > 3)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("betarnd: dimensions must be non-negative integers");
     endif
-  elseif (nargin == 2)
-    sz = size(a);
-  else
-    print_usage ();
+    sz = [varargin{:}];
   endif
 
-  if (isscalar(a) && isscalar(b))
-    if (find (!(a > 0) | !(a < Inf) | !(b > 0) | !(b < Inf)))
-      rnd = NaN (sz);
+  if (!isscalar (a) && !isequal (size (a), sz))
+    error ("betarnd: A and B must be scalar or of size SZ");
+  endif
+
+  if (isa (a, "single") || isa (b, "single"))
+    cls = "single";
+  else
+    cls = "double";
+  endif
+
+  if (isscalar (a) && isscalar (b))
+    if ((a > 0) && (a < Inf) && (b > 0) && (b < Inf))
+      r = randg (a, sz);
+      rnd = r ./ (r + randg (b, sz));
+      if (strcmp (cls, "single"))
+        rnd = single (rnd);
+      endif
     else
-      r1 = randg(a,sz);
-      rnd = r1 ./ (r1 + randg(b,sz));
+      rnd = NaN (sz, cls);
     endif
   else
-    rnd = zeros (sz);
+    rnd = NaN (sz, cls);
 
-    k = find (!(a > 0) | !(a < Inf) | !(b > 0) | !(b < Inf));
-    if (any (k))
-      rnd(k) = NaN (size (k));
-    endif
-
-    k = find ((a > 0) & (a < Inf) & (b > 0) & (b < Inf));
-    if (any (k))
-      r1 = randg(a(k),size(k));
-      rnd(k) = r1 ./ (r1 + randg(b(k),size(k)));
-    endif
+    k = (a > 0) & (a < Inf) & (b > 0) & (b < Inf);
+    r = randg (a(k));
+    rnd(k) = r ./ (r + randg (b(k)));
   endif
 
 endfunction
+
+
+%!assert(size (betarnd (1,2)), [1, 1]);
+%!assert(size (betarnd (ones(2,1), 2)), [2, 1]);
+%!assert(size (betarnd (ones(2,2), 2)), [2, 2]);
+%!assert(size (betarnd (1, 2*ones(2,1))), [2, 1]);
+%!assert(size (betarnd (1, 2*ones(2,2))), [2, 2]);
+%!assert(size (betarnd (1, 2, 3)), [3, 3]);
+%!assert(size (betarnd (1, 2, [4 1])), [4, 1]);
+%!assert(size (betarnd (1, 2, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (betarnd (1, 2)), "double");
+%!assert(class (betarnd (single(1), 2)), "single");
+%!assert(class (betarnd (single([1 1]), 2)), "single");
+%!assert(class (betarnd (1, single(2))), "single");
+%!assert(class (betarnd (1, single([2 2]))), "single");
+
+%% Test input validation
+%!error betarnd ()
+%!error betarnd (1)
+%!error betarnd (ones(3),ones(2))
+%!error betarnd (ones(2),ones(3))
+%!error betarnd (i, 2)
+%!error betarnd (2, i)
+%!error betarnd (1,2, -1)
+%!error betarnd (1,2, ones(2))
+%!error binornd (1,2, [2 -1 2])
+%!error betarnd (1,2, 1, ones(2))
+%!error betarnd (1,2, 1, -1)
+%!error betarnd (ones(2,2), 2, 3)
+%!error betarnd (ones(2,2), 2, [3, 2])
+%!error betarnd (ones(2,2), 2, 2, 3)
+
--- a/scripts/statistics/distributions/binocdf.m
+++ b/scripts/statistics/distributions/binocdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,8 +19,9 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} binocdf (@var{x}, @var{n}, @var{p})
-## For each element of @var{x}, compute the CDF at @var{x} of the
-## binomial distribution with parameters @var{n} and @var{p}.
+## For each element of @var{x}, compute the cumulative distribution function
+## (CDF) at @var{x} of the binomial distribution with parameters @var{n} and
+## @var{p}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -34,34 +36,62 @@
   if (!isscalar (n) || !isscalar (p))
     [retval, x, n, p] = common_size (x, n, p);
     if (retval > 0)
-      error ("binocdf: X, N and P must be of common size or scalar");
+      error ("binocdf: X, N, and P must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  cdf = zeros (sz);
+  if (iscomplex (x) || iscomplex (n) || iscomplex (p))
+    error ("binocdf: X, N, and P must not be complex");
+  endif
 
-  k = find (isnan (x) | !(n >= 0) | (n != round (n))
-            | !(p >= 0) | !(p <= 1));
-  if (any (k))
-    cdf(k) = NaN;
+  if (isa (x, "single") || isa (n, "single") || isa (p, "single"));
+    cdf = zeros (size (x), "single");
+  else
+    cdf = zeros (size (x));
   endif
 
-  k = find ((x >= n) & (n >= 0) & (n == round (n))
-            & (p >= 0) & (p <= 1));
-  if (any (k))
-    cdf(k) = 1;
-  endif
+  k = isnan (x) | !(n >= 0) | (n != fix (n)) | !(p >= 0) | !(p <= 1);
+  cdf(k) = NaN;
+
+  k = (x >= n) & (n >= 0) & (n == fix (n) & (p >= 0) & (p <= 1));
+  cdf(k) = 1;
 
-  k = find ((x >= 0) & (x < n) & (n == round (n))
-            & (p >= 0) & (p <= 1));
-  if (any (k))
-    tmp = floor (x(k));
-    if (isscalar (n) && isscalar (p))
-      cdf(k) = 1 - betainc (p, tmp + 1, n - tmp);
-    else
-      cdf(k) = 1 - betainc (p(k), tmp + 1, n(k) - tmp);
-    endif
+  k = (x >= 0) & (x < n) & (n == fix (n)) & (p >= 0) & (p <= 1);
+  tmp = floor (x(k));
+  if (isscalar (n) && isscalar (p))
+    cdf(k) = 1 - betainc (p, tmp + 1, n - tmp);
+  else
+    cdf(k) = 1 - betainc (p(k), tmp + 1, n(k) - tmp);
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 1 2 3];
+%! y = [0 1/4 3/4 1 1];
+%!assert(binocdf (x, 2*ones(1,5), 0.5*ones(1,5)), y);
+%!assert(binocdf (x, 2, 0.5*ones(1,5)), y);
+%!assert(binocdf (x, 2*ones(1,5), 0.5), y);
+%!assert(binocdf (x, 2*[0 -1 NaN 1.1 1], 0.5), [0 NaN NaN NaN 1]);
+%!assert(binocdf (x, 2, 0.5*[0 -1 NaN 3 1]), [0 NaN NaN NaN 1]);
+%!assert(binocdf ([x(1:2) NaN x(4:5)], 2, 0.5), [y(1:2) NaN y(4:5)]);
+
+%% Test class of input preserved
+%!assert(binocdf ([x, NaN], 2, 0.5), [y, NaN]);
+%!assert(binocdf (single([x, NaN]), 2, 0.5), single([y, NaN]));
+%!assert(binocdf ([x, NaN], single(2), 0.5), single([y, NaN]));
+%!assert(binocdf ([x, NaN], 2, single(0.5)), single([y, NaN]));
+
+%% Test input validation
+%!error binocdf ()
+%!error binocdf (1)
+%!error binocdf (1,2)
+%!error binocdf (1,2,3,4)
+%!error binocdf (ones(3),ones(2),ones(2))
+%!error binocdf (ones(2),ones(3),ones(2))
+%!error binocdf (ones(2),ones(2),ones(3))
+%!error binocdf (i, 2, 2)
+%!error binocdf (2, i, 2)
+%!error binocdf (2, 2, i)
+
--- a/scripts/statistics/distributions/binoinv.m
+++ b/scripts/statistics/distributions/binoinv.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,8 +19,9 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} binoinv (@var{x}, @var{n}, @var{p})
-## For each element of @var{x}, compute the quantile at @var{x} of the
-## binomial distribution with parameters @var{n} and @var{p}.
+## For each element of @var{x}, compute the quantile (the inverse of
+## the CDF) at @var{x} of the binomial distribution with parameters 
+## @var{n} and @var{p}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -34,24 +36,29 @@
   if (!isscalar (n) || !isscalar (p))
     [retval, x, n, p] = common_size (x, n, p);
     if (retval > 0)
-      error ("binoinv: X, N and P must be of common size or scalars");
+      error ("binoinv: X, N, and P must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  inv = zeros (sz);
+  if (iscomplex (x) || iscomplex (n) || iscomplex (p))
+    error ("binoinv: X, N, and P must not be complex");
+  endif
 
-  k = find (!(x >= 0) | !(x <= 1) | !(n >= 0) | (n != round (n))
-            | !(p >= 0) | !(p <= 1));
-  if (any (k))
-    inv(k) = NaN;
+  if (isa (x, "single") || isa (n, "single") || isa (p, "single"));
+    inv = zeros (size (x), "single");
+  else
+    inv = zeros (size (x));
   endif
 
-  k = find ((x >= 0) & (x <= 1) & (n >= 0) & (n == round (n))
-            & (p >= 0) & (p <= 1));
+  k = (!(x >= 0) | !(x <= 1) | !(n >= 0) | (n != fix (n)) |
+       !(p >= 0) | !(p <= 1));
+  inv(k) = NaN;
+
+  k = find ((x >= 0) & (x <= 1) & (n >= 0) & (n == fix (n)
+             & (p >= 0) & (p <= 1)));
   if (any (k))
     if (isscalar (n) && isscalar (p))
-      cdf = binopdf (0, n, p) * ones (size(k));
+      cdf = binopdf (0, n, p) * ones (size (k));
       while (any (inv(k) < n))
         m = find (cdf < x(k));
         if (any (m))
@@ -76,3 +83,32 @@
   endif
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.5 1 2];
+%!assert(binoinv (x, 2*ones(1,5), 0.5*ones(1,5)), [NaN 0 1 2 NaN]);
+%!assert(binoinv (x, 2, 0.5*ones(1,5)), [NaN 0 1 2 NaN]);
+%!assert(binoinv (x, 2*ones(1,5), 0.5), [NaN 0 1 2 NaN]);
+%!assert(binoinv (x, 2*[0 -1 NaN 1.1 1], 0.5), [NaN NaN NaN NaN NaN]);
+%!assert(binoinv (x, 2, 0.5*[0 -1 NaN 3 1]), [NaN NaN NaN NaN NaN]);
+%!assert(binoinv ([x(1:2) NaN x(4:5)], 2, 0.5), [NaN 0 NaN 2 NaN]);
+
+%% Test class of input preserved
+%!assert(binoinv ([x, NaN], 2, 0.5), [NaN 0 1 2 NaN NaN]);
+%!assert(binoinv (single([x, NaN]), 2, 0.5), single([NaN 0 1 2 NaN NaN]));
+%!assert(binoinv ([x, NaN], single(2), 0.5), single([NaN 0 1 2 NaN NaN]));
+%!assert(binoinv ([x, NaN], 2, single(0.5)), single([NaN 0 1 2 NaN NaN]));
+
+%% Test input validation
+%!error binoinv ()
+%!error binoinv (1)
+%!error binoinv (1,2)
+%!error binoinv (1,2,3,4)
+%!error binoinv (ones(3),ones(2),ones(2))
+%!error binoinv (ones(2),ones(3),ones(2))
+%!error binoinv (ones(2),ones(2),ones(3))
+%!error binoinv (i, 2, 2)
+%!error binoinv (2, i, 2)
+%!error binoinv (2, 2, i)
+
--- a/scripts/statistics/distributions/binopdf.m
+++ b/scripts/statistics/distributions/binopdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -35,26 +36,60 @@
   if (! isscalar (n) || ! isscalar (p))
     [retval, x, n, p] = common_size (x, n, p);
     if (retval > 0)
-      error ("binopdf: X, N and P must be of common size or scalar");
+      error ("binopdf: X, N, and P must be of common size or scalars");
     endif
   endif
 
-  k = ((x >= 0) & (x <= n)
-       & (x == round (x)) & (n == round (n))
-       & (p >= 0) & (p <= 1));
+  if (iscomplex (x) || iscomplex (n) || iscomplex (p))
+    error ("binopdf: X, N, and P must not be complex");
+  endif
 
-  pdf = zeros (size (x));
+  if (isa (x, "single") || isa (n, "single") || isa (p, "single"));
+    pdf = zeros (size (x), "single");
+  else
+    pdf = zeros (size (x));
+  endif
+
+  k = (x == fix (x)) & (n == fix (n)) & (n >= 0) & (p >= 0) & (p <= 1);
+
   pdf(! k) = NaN;
-  if (any (k(:)))
-    x = x(k);
-    if (! isscalar (n))
-      n = n(k);
-    endif
-    if (! isscalar (p))
-      p = p(k);
-    endif
-    z = gammaln(n+1) - gammaln(x+1) - gammaln(n-x+1) + x.*log(p) + (n-x).*log(1-p);
-    pdf(k) = exp (z);
+
+  k &= ((x >= 0) & (x <= n));
+  if (isscalar (n) && isscalar (p))
+    pdf(k) = exp (gammaln (n+1) - gammaln (x(k)+1) - gammaln (n-x(k)+1)
+                  + x(k)*log (p) + (n-x(k))*log (1-p));
+  else
+    pdf(k) = exp (gammaln (n(k)+1) - gammaln (x(k)+1) - gammaln (n(k)-x(k)+1)
+                  + x(k).*log (p(k)) + (n(k)-x(k)).*log (1-p(k)));
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 1 2 3];
+%! y = [0 1/4 1/2 1/4 0];
+%!assert(binopdf (x, 2*ones(1,5), 0.5*ones(1,5)), y);
+%!assert(binopdf (x, 2, 0.5*ones(1,5)), y);
+%!assert(binopdf (x, 2*ones(1,5), 0.5), y);
+%!assert(binopdf (x, 2*[0 -1 NaN 1.1 1], 0.5), [0 NaN NaN NaN 0]);
+%!assert(binopdf (x, 2, 0.5*[0 -1 NaN 3 1]), [0 NaN NaN NaN 0]);
+%!assert(binopdf ([x, NaN], 2, 0.5), [y, NaN]);
+
+%% Test class of input preserved
+%!assert(binopdf (single([x, NaN]), 2, 0.5), single([y, NaN]));
+%!assert(binopdf ([x, NaN], single(2), 0.5), single([y, NaN]));
+%!assert(binopdf ([x, NaN], 2, single(0.5)), single([y, NaN]));
+
+%% Test input validation
+%!error binopdf ()
+%!error binopdf (1)
+%!error binopdf (1,2)
+%!error binopdf (1,2,3,4)
+%!error binopdf (ones(3),ones(2),ones(2))
+%!error binopdf (ones(2),ones(3),ones(2))
+%!error binopdf (ones(2),ones(2),ones(3))
+%!error binopdf (i, 2, 2)
+%!error binopdf (2, i, 2)
+%!error binopdf (2, 2, i)
+
--- a/scripts/statistics/distributions/binornd.m
+++ b/scripts/statistics/distributions/binornd.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,96 +18,136 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} binornd (@var{n}, @var{p}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} binornd (@var{n}, @var{p}, @var{sz})
-## Return an @var{r} by @var{c}  or a @code{size (@var{sz})} matrix of
-## random samples from the binomial distribution with parameters @var{n}
-## and @var{p}.  Both @var{n} and @var{p} must be scalar or of size
-## @var{r} by @var{c}.
+## @deftypefn  {Function File} {} binornd (@var{n}, @var{p})
+## @deftypefnx {Function File} {} binornd (@var{n}, @var{p}, @var{r})
+## @deftypefnx {Function File} {} binornd (@var{n}, @var{p}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} binornd (@var{n}, @var{p}, [@var{sz}])
+## Return a matrix of random samples from the binonmial distribution with
+## parameters @var{n} and @var{p}.
 ##
-## If @var{r} and @var{c} are omitted, the size of the result matrix is
-## the common size of @var{n} and @var{p}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the common size of
+## @var{n} and @var{p}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the binomial distribution
 
-function rnd = binornd (n, p, r, c)
+function rnd = binornd (n, p, varargin)
 
-  if (nargin > 1)
-    if (!isscalar(n) || !isscalar(p))
-      [retval, n, p] = common_size (n, p);
-      if (retval > 0)
-        error ("binornd: N and P must be of common size or scalar");
-      endif
+  if (nargin < 2)
+    print_usage ();
+  endif
+
+  if (!isscalar (n) || !isscalar (p))
+    [retval, n, p] = common_size (n, p);
+    if (retval > 0)
+      error ("binornd: N and P must be of common size or scalars");
     endif
   endif
 
-  if (nargin == 4)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("binornd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("binornd: C must be a positive integer");
-    endif
-    sz = [r, c];
+  if (iscomplex (n) || iscomplex (p))
+    error ("binornd: N and P must not be complex");
+  endif
 
-    if (any (size (n) != 1)
-        && (length (size (n)) != length (sz) || any (size (n) != sz)))
-      error ("binornd: N and must be scalar or of size [R, C]");
-    endif
+  if (nargin == 2)
+    sz = size (n);
   elseif (nargin == 3)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
     else
-      error ("binornd: R must be a positive integer or vector");
+      error ("binornd: dimension vector must be row vector of non-negative integers");
     endif
+  elseif (nargin > 3)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("binornd: dimensions must be non-negative integers");
+    endif
+    sz = [varargin{:}];
+  endif
 
-    if (any (size (n) != 1)
-        && (length (size (n)) != length (sz) || any (size (n) != sz)))
-      error ("binornd: N and must be scalar or of size SZ");
-    endif
-  elseif (nargin == 2)
-    sz = size(n);
+  if (!isscalar (n) && !isequal (size (n), sz))
+    error ("binornd: N and P must be scalar or of size SZ");
+  endif
+
+  if (isa (n, "single") || isa (p, "single"))
+    cls = "single";
   else
-    print_usage ();
+    cls = "double";
   endif
 
   if (isscalar (n) && isscalar (p))
-    if (find (!(n >= 0) | !(n < Inf) | !(n == round (n)) |
-              !(p >= 0) | !(p <= 1)))
-      rnd = NaN (sz);
-    elseif (n == 0)
-      rnd = zeros (sz);
-    else
+    if ((n > 0) && (n < Inf) && (n == fix (n)) && (p >= 0) && (p <= 1))
       nel = prod (sz);
       tmp = rand (n, nel);
-      rnd = sum(tmp < ones (n, nel) * p, 1);
-      rnd = reshape(rnd, sz);
+      rnd = sum (tmp < p, 1);
+      rnd = reshape (rnd, sz);
+      if (strcmp (cls, "single"))
+        rnd = single (rnd);
+      endif
+    elseif ((n == 0) && (p >= 0) && (p <= 1))
+      rnd = zeros (sz, cls);
+    else
+      rnd = NaN (sz, cls);
     endif
   else
-    rnd = zeros (sz);
+    rnd = zeros (sz, cls);
 
-    k = find (!(n >= 0) | !(n < Inf) | !(n == round (n)) |
-              !(p >= 0) | !(p <= 1));
-    if (any (k))
-      rnd(k) = NaN;
-    endif
+    k = !(n >= 0) | !(n < Inf) | !(n == fix (n)) | !(p >= 0) | !(p <= 1);
+    rnd(k) = NaN;
 
-    k = find ((n > 0) & (n < Inf) & (n == round (n)) & (p >= 0) & (p <= 1));
-    if (any (k))
+    k = (n > 0) & (n < Inf) & (n == fix (n)) & (p >= 0) & (p <= 1);
+    if (any (k(:)))
       N = max (n(k));
-      L = length (k);
+      L = sum (k(:));
       tmp = rand (N, L);
-      ind = (1 : N)' * ones (1, L);
-      rnd(k) = sum ((tmp < ones (N, 1) * p(k)(:)') &
-                    (ind <= ones (N, 1) * n(k)(:)'),1);
+      ind = repmat ((1 : N)', 1, L);
+      rnd(k) = sum ((tmp < repmat (p(k)(:)', N, 1)) &
+                    (ind <= repmat (n(k)(:)', N, 1)), 1);
     endif
   endif
 
 endfunction
 
-%!assert (binornd(0, 0, 1), 0)
-%!assert (binornd([0, 0], [0, 0], 1, 2), [0, 0])
+
+%!assert (binornd (0, 0, 1), 0)
+%!assert (binornd ([0, 0], [0, 0], 1, 2), [0, 0])
+
+%!assert(size (binornd (2, 1/2)), [1, 1]);
+%!assert(size (binornd (2*ones(2,1), 1/2)), [2, 1]);
+%!assert(size (binornd (2*ones(2,2), 1/2)), [2, 2]);
+%!assert(size (binornd (2, 1/2*ones(2,1))), [2, 1]);
+%!assert(size (binornd (2, 1/2*ones(2,2))), [2, 2]);
+%!assert(size (binornd (2, 1/2, 3)), [3, 3]);
+%!assert(size (binornd (2, 1/2, [4 1])), [4, 1]);
+%!assert(size (binornd (2, 1/2, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (binornd (2, 0.5)), "double");
+%!assert(class (binornd (single(2), 0.5)), "single");
+%!assert(class (binornd (single([2 2]), 0.5)), "single");
+%!assert(class (binornd (2, single(0.5))), "single");
+%!assert(class (binornd (2, single([0.5 0.5]))), "single");
+
+%% Test input validation
+%!error binornd ()
+%!error binornd (1)
+%!error binornd (ones(3),ones(2))
+%!error binornd (ones(2),ones(3))
+%!error binornd (i, 2)
+%!error binornd (2, i)
+%!error binornd (1,2, -1)
+%!error binornd (1,2, ones(2))
+%!error binornd (1,2, [2 -1 2])
+%!error binornd (1,2, 1, ones(2))
+%!error binornd (1,2, 1, -1)
+%!error binornd (ones(2,2), 2, 3)
+%!error binornd (ones(2,2), 2, [3, 2])
+%!error binornd (ones(2,2), 2, 2, 3)
+
--- a/scripts/statistics/distributions/cauchy_cdf.m
+++ b/scripts/statistics/distributions/cauchy_cdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,7 +18,8 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} cauchy_cdf (@var{x}, @var{location}, @var{scale})
+## @deftypefn  {Function File} {} cauchy_cdf (@var{x})
+## @deftypefnx {Function File} {} cauchy_cdf (@var{x}, @var{location}, @var{scale})
 ## For each element of @var{x}, compute the cumulative distribution
 ## function (CDF) at @var{x} of the Cauchy distribution with location
 ## parameter @var{location} and scale parameter @var{scale}.  Default
@@ -27,35 +29,63 @@
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: CDF of the Cauchy distribution
 
-function cdf = cauchy_cdf (x, location, scale)
+function cdf = cauchy_cdf (x, location = 0, scale = 1)
 
-  if (! (nargin == 1 || nargin == 3))
+  if (nargin != 1 && nargin != 3)
     print_usage ();
   endif
 
-  if (nargin == 1)
-    location = 0;
-    scale = 1;
-  endif
-
   if (!isscalar (location) || !isscalar (scale))
     [retval, x, location, scale] = common_size (x, location, scale);
     if (retval > 0)
-      error ("cauchy_cdf: X, LOCATION and SCALE must be of common size or scalar");
+      error ("cauchy_cdf: X, LOCATION, and SCALE must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  cdf = NaN (sz);
+  if (iscomplex (x) || iscomplex (location) || iscomplex (scale))
+    error ("cauchy_cdf: X, LOCATION, and SCALE must not be complex");
+  endif
 
-  k = find (ones (sz) & (location > -Inf) & (location < Inf)
-                      & (scale > 0) & (scale < Inf));
-  if (any (k))
-    if (isscalar (location) && isscalar (scale))
-      cdf(k) = 0.5 + atan ((x(k) - location) ./ scale) / pi;
-    else
-      cdf(k) = 0.5 + atan ((x(k) - location(k)) ./ scale(k)) / pi;
-    endif
+  if (isa (x, "single") || isa (location, "single") || isa (scale, "single"));
+    cdf = NaN (size (x), "single");
+  else
+    cdf = NaN (size (x));
+  endif
+
+  k = !isinf (location) & (scale > 0) & (scale < Inf);
+  if (isscalar (location) && isscalar (scale))
+    cdf = 0.5 + atan ((x - location) / scale) / pi;
+  else
+    cdf(k) = 0.5 + atan ((x(k) - location(k)) ./ scale(k)) / pi;
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 0.5 1 2];
+%! y = 1/pi * atan ((x-1) / 2) + 1/2;
+%!assert(cauchy_cdf (x, ones(1,5), 2*ones(1,5)), y);
+%!assert(cauchy_cdf (x, 1, 2*ones(1,5)), y);
+%!assert(cauchy_cdf (x, ones(1,5), 2), y);
+%!assert(cauchy_cdf (x, [-Inf 1 NaN 1 Inf], 2), [NaN y(2) NaN y(4) NaN]);
+%!assert(cauchy_cdf (x, 1, 2*[0 1 NaN 1 Inf]), [NaN y(2) NaN y(4) NaN]);
+%!assert(cauchy_cdf ([x(1:2) NaN x(4:5)], 1, 2), [y(1:2) NaN y(4:5)]);
+
+%% Test class of input preserved
+%!assert(cauchy_cdf ([x, NaN], 1, 2), [y, NaN]);
+%!assert(cauchy_cdf (single([x, NaN]), 1, 2), single([y, NaN]), eps("single"));
+%!assert(cauchy_cdf ([x, NaN], single(1), 2), single([y, NaN]), eps("single"));
+%!assert(cauchy_cdf ([x, NaN], 1, single(2)), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error cauchy_cdf ()
+%!error cauchy_cdf (1,2)
+%!error cauchy_cdf (1,2,3,4)
+%!error cauchy_cdf (ones(3),ones(2),ones(2))
+%!error cauchy_cdf (ones(2),ones(3),ones(2))
+%!error cauchy_cdf (ones(2),ones(2),ones(3))
+%!error cauchy_cdf (i, 2, 2)
+%!error cauchy_cdf (2, i, 2)
+%!error cauchy_cdf (2, 2, i)
+
--- a/scripts/statistics/distributions/cauchy_inv.m
+++ b/scripts/statistics/distributions/cauchy_inv.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,7 +18,8 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} cauchy_inv (@var{x}, @var{location}, @var{scale})
+## @deftypefn  {Function File} {} cauchy_inv (@var{x})
+## @deftypefnx {Function File} {} cauchy_inv (@var{x}, @var{location}, @var{scale})
 ## For each element of @var{x}, compute the quantile (the inverse of the
 ## CDF) at @var{x} of the Cauchy distribution with location parameter
 ## @var{location} and scale parameter @var{scale}.  Default values are
@@ -27,47 +29,70 @@
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Quantile function of the Cauchy distribution
 
-function inv = cauchy_inv (x, location, scale)
+function inv = cauchy_inv (x, location = 0, scale = 1)
 
-  if (! (nargin == 1 || nargin == 3))
+  if (nargin != 1 && nargin != 3)
     print_usage ();
   endif
 
-  if (nargin == 1)
-    location = 0;
-    scale = 1;
-  endif
-
   if (!isscalar (location) || !isscalar (scale))
     [retval, x, location, scale] = common_size (x, location, scale);
     if (retval > 0)
-      error ("cauchy_inv: X, LOCATION and SCALE must be of common size or scalar");
+      error ("cauchy_inv: X, LOCATION, and SCALE must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  inv = NaN (sz);
+  if (iscomplex (x) || iscomplex (location) || iscomplex (scale))
+    error ("cauchy_inv: X, LOCATION, and SCALE must not be complex");
+  endif
 
-  ok = ((location > -Inf) & (location < Inf) &
-       (scale > 0) & (scale < Inf));
-
-  k = find ((x == 0) & ok);
-  if (any (k))
-    inv(k) = -Inf;
+  if (isa (x, "single") || isa (location, "single") || isa (scale, "single"))
+    inv = NaN (size (x), "single");
+  else
+    inv = NaN (size (x));
   endif
 
-  k = find ((x > 0) & (x < 1) & ok);
-  if (any (k))
-    if (isscalar (location) && isscalar (scale))
-      inv(k) = location - scale .* cot (pi * x(k));
-    else
-      inv(k) = location(k) - scale(k) .* cot (pi * x(k));
-    endif
-  endif
+  ok = !isinf (location) & (scale > 0) & (scale < Inf);
+
+  k = (x == 0) & ok;
+  inv(k) = -Inf;
 
-  k = find ((x == 1) & ok);
-  if (any (k))
-    inv(k) = Inf;
+  k = (x == 1) & ok;
+  inv(k) = Inf;
+
+  k = (x > 0) & (x < 1) & ok;
+  if (isscalar (location) && isscalar (scale))
+    inv(k) = location - scale * cot (pi * x(k));
+  else
+    inv(k) = location(k) - scale(k) .* cot (pi * x(k));
   endif
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.5 1 2];
+%!assert(cauchy_inv (x, ones(1,5), 2*ones(1,5)), [NaN -Inf 1 Inf NaN], eps);
+%!assert(cauchy_inv (x, 1, 2*ones(1,5)), [NaN -Inf 1 Inf NaN], eps);
+%!assert(cauchy_inv (x, ones(1,5), 2), [NaN -Inf 1 Inf NaN], eps);
+%!assert(cauchy_inv (x, [1 -Inf NaN Inf 1], 2), [NaN NaN NaN NaN NaN]);
+%!assert(cauchy_inv (x, 1, 2*[1 0 NaN Inf 1]), [NaN NaN NaN NaN NaN]);
+%!assert(cauchy_inv ([x(1:2) NaN x(4:5)], 1, 2), [NaN -Inf NaN Inf NaN]);
+
+%% Test class of input preserved
+%!assert(cauchy_inv ([x, NaN], 1, 2), [NaN -Inf 1 Inf NaN NaN], eps);
+%!assert(cauchy_inv (single([x, NaN]), 1, 2), single([NaN -Inf 1 Inf NaN NaN]), eps("single"));
+%!assert(cauchy_inv ([x, NaN], single(1), 2), single([NaN -Inf 1 Inf NaN NaN]), eps("single"));
+%!assert(cauchy_inv ([x, NaN], 1, single(2)), single([NaN -Inf 1 Inf NaN NaN]), eps("single"));
+
+%% Test input validation
+%!error cauchy_inv ()
+%!error cauchy_inv (1,2)
+%!error cauchy_inv (1,2,3,4)
+%!error cauchy_inv (ones(3),ones(2),ones(2))
+%!error cauchy_inv (ones(2),ones(3),ones(2))
+%!error cauchy_inv (ones(2),ones(2),ones(3))
+%!error cauchy_inv (i, 2, 2)
+%!error cauchy_inv (2, i, 2)
+%!error cauchy_inv (2, 2, i)
+
--- a/scripts/statistics/distributions/cauchy_pdf.m
+++ b/scripts/statistics/distributions/cauchy_pdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,7 +18,8 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} cauchy_pdf (@var{x}, @var{location}, @var{scale})
+## @deftypefn  {Function File} {} cauchy_pdf (@var{x})
+## @deftypefnx {Function File} {} cauchy_pdf (@var{x}, @var{location}, @var{scale})
 ## For each element of @var{x}, compute the probability density function
 ## (PDF) at @var{x} of the Cauchy distribution with location parameter
 ## @var{location} and scale parameter @var{scale} > 0.  Default values are
@@ -27,37 +29,69 @@
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: PDF of the Cauchy distribution
 
-function pdf = cauchy_pdf (x, location, scale)
+function pdf = cauchy_pdf (x, location = 0, scale = 1)
 
-  if (! (nargin == 1 || nargin == 3))
+  if (nargin != 1 && nargin != 3)
     print_usage ();
   endif
 
-  if (nargin == 1)
-    location = 0;
-    scale = 1;
-  endif
-
   if (!isscalar (location) || !isscalar (scale))
     [retval, x, location, scale] = common_size (x, location, scale);
     if (retval > 0)
-      error ("cauchy_pdf: X, LOCATION and SCALE must be of common size or scalar");
+      error ("cauchy_pdf: X, LOCATION, and SCALE must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  pdf = NaN (sz);
+  if (iscomplex (x) || iscomplex (location) || iscomplex (scale))
+    error ("cauchy_pdf: X, LOCATION, and SCALE must not be complex");
+  endif
 
-  k = find ((x > -Inf) & (x < Inf) & (location > -Inf) &
-            (location < Inf) & (scale > 0) & (scale < Inf));
-  if (any (k))
-    if (isscalar (location) && isscalar (scale))
-      pdf(k) = ((1 ./ (1 + ((x(k) - location) ./ scale) .^ 2))
-                / pi ./ scale);
-    else
-      pdf(k) = ((1 ./ (1 + ((x(k) - location(k)) ./ scale(k)) .^ 2))
-                / pi ./ scale(k));
-    endif
+  if (isa (x, "single") || isa (location, "single") || isa (scale, "single"))
+    pdf = NaN (size (x), "single");
+  else
+    pdf = NaN (size (x));
+  endif
+
+  k = !isinf (location) & (scale > 0) & (scale < Inf);
+  if (isscalar (location) && isscalar (scale))
+    pdf = ((1 ./ (1 + ((x - location) / scale) .^ 2))
+              / pi / scale);
+  else
+    pdf(k) = ((1 ./ (1 + ((x(k) - location(k)) ./ scale(k)) .^ 2))
+              / pi ./ scale(k));
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 0.5 1 2];
+%! y = 1/pi * ( 2 ./ ((x-1).^2 + 2^2) );
+%!assert(cauchy_pdf (x, ones(1,5), 2*ones(1,5)), y);
+%!assert(cauchy_pdf (x, 1, 2*ones(1,5)), y);
+%!assert(cauchy_pdf (x, ones(1,5), 2), y);
+%!assert(cauchy_pdf (x, [-Inf 1 NaN 1 Inf], 2), [NaN y(2) NaN y(4) NaN]);
+%!assert(cauchy_pdf (x, 1, 2*[0 1 NaN 1 Inf]), [NaN y(2) NaN y(4) NaN]);
+%!assert(cauchy_pdf ([x, NaN], 1, 2), [y, NaN]);
+
+%% Test class of input preserved
+%!assert(cauchy_pdf (single([x, NaN]), 1, 2), single([y, NaN]), eps("single"));
+%!assert(cauchy_pdf ([x, NaN], single(1), 2), single([y, NaN]), eps("single"));
+%!assert(cauchy_pdf ([x, NaN], 1, single(2)), single([y, NaN]), eps("single"));
+
+%% Cauchy (0,1) == Student's T distribution with 1 DOF
+%!test
+%! x = rand (10, 1);
+%! assert(cauchy_pdf (x, 0, 1), tpdf (x, 1), eps);
+
+%% Test input validation
+%!error cauchy_pdf ()
+%!error cauchy_pdf (1,2)
+%!error cauchy_pdf (1,2,3,4)
+%!error cauchy_pdf (ones(3),ones(2),ones(2))
+%!error cauchy_pdf (ones(2),ones(3),ones(2))
+%!error cauchy_pdf (ones(2),ones(2),ones(3))
+%!error cauchy_pdf (i, 2, 2)
+%!error cauchy_pdf (2, i, 2)
+%!error cauchy_pdf (2, 2, i)
+
--- a/scripts/statistics/distributions/cauchy_rnd.m
+++ b/scripts/statistics/distributions/cauchy_rnd.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,78 +18,115 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} cauchy_rnd (@var{location}, @var{scale}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} cauchy_rnd (@var{location}, @var{scale}, @var{sz})
-## Return an @var{r} by @var{c} or a @code{size (@var{sz})} matrix of
-## random samples from the Cauchy distribution with parameters @var{location}
-## and @var{scale} which must both be scalar or of size @var{r} by @var{c}.
+## @deftypefn  {Function File} {} cauchy_rnd (@var{location}, @var{scale})
+## @deftypefnx {Function File} {} cauchy_rnd (@var{location}, @var{scale}, @var{r})
+## @deftypefnx {Function File} {} cauchy_rnd (@var{location}, @var{scale}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} cauchy_rnd (@var{location}, @var{scale}, [@var{sz}])
+## Return a matrix of random samples from the Cauchy distribution with
+## parameters @var{location} and @var{scale}.
 ##
-## If @var{r} and @var{c} are omitted, the size of the result matrix is
-## the common size of @var{location} and @var{scale}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the common size of
+## @var{location} and @var{scale}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the Cauchy distribution
 
-function rnd = cauchy_rnd (location, scale, r, c)
+function rnd = cauchy_rnd (location, scale, varargin)
 
-  if (nargin > 1)
-    if (!isscalar (location) || !isscalar (scale))
-      [retval, location, scale] = common_size (location, scale);
-      if (retval > 0)
-        error ("cauchy_rnd: LOCATION and SCALE must be of common size or scalar");
-      endif
+  if (nargin < 2)
+    print_usage ();
+  endif
+
+  if (!isscalar (location) || !isscalar (scale))
+    [retval, location, scale] = common_size (location, scale);
+    if (retval > 0)
+      error ("cauchy_rnd: LOCATION and SCALE must be of common size or scalars");
     endif
   endif
 
-  if (nargin == 4)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("cauchy_rnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("cauchy_rnd: C must be a positive integer");
-    endif
-    sz = [r, c];
+  if (iscomplex (location) || iscomplex (scale))
+    error ("cauchy_rnd: LOCATION and SCALE must not be complex");
+  endif
 
-    if (any (size (location) != 1)
-        && (length (size (location)) != length (sz)
-            || any (size (location) != sz)))
-      error ("cauchy_rnd: LOCATION and SCALE must be scalar or of size [R, C]");
-    endif
+  if (nargin == 2)
+    sz = size (location);
   elseif (nargin == 3)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
     else
-      error ("cauchy_rnd: R must be a positive integer or vector");
+      error ("cauchy_rnd: dimension vector must be row vector of non-negative integers");
     endif
+  elseif (nargin > 3)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("cauchy_rnd: dimensions must be non-negative integers");
+    endif
+    sz = [varargin{:}];
+  endif
 
-    if (any (size (location) != 1)
-        && (length (size (location)) != length (sz)
-        || any (size (location) != sz)))
-      error ("cauchy_rnd: LOCATION and SCALE must be scalar or of size SZ");
-    endif
-  elseif (nargin == 2)
-    sz = size(location);
+  if (!isscalar (location) && !isequal (size (location), sz))
+    error ("cauchy_rnd: LOCATION and SCALE must be scalar or of size SZ");
+  endif
+
+  if (isa (location, "single") || isa (scale, "single"))
+    cls = "single";
   else
-    print_usage ();
+    cls = "double";
   endif
 
   if (isscalar (location) && isscalar (scale))
-    if (find (!(location > -Inf) | !(location < Inf)
-                | !(scale > 0) | !(scale < Inf)))
-      rnd = NaN (sz);
+    if (!isinf (location) && (scale > 0) && (scale < Inf))
+      rnd = location - cot (pi * rand (sz)) * scale;
     else
-      rnd = location - cot (pi * rand (sz)) .* scale;
+      rnd = NaN (sz, cls);
     endif
   else
-    rnd = NaN (sz);
-    k = find ((location > -Inf) & (location < Inf)
-              & (scale > 0) & (scale < Inf));
-    if (any (k))
-      rnd(k) = location(k)(:) - cot (pi * rand (size (k))) .* scale(k)(:);
-    endif
+    rnd = NaN (sz, cls);
+
+    k = !isinf (location) & (scale > 0) & (scale < Inf);
+    rnd(k) = location(k)(:) - cot (pi * rand (sum (k(:)), 1)) .* scale(k)(:);
   endif
 
 endfunction
+
+
+%!assert(size (cauchy_rnd (1,2)), [1, 1]);
+%!assert(size (cauchy_rnd (ones(2,1), 2)), [2, 1]);
+%!assert(size (cauchy_rnd (ones(2,2), 2)), [2, 2]);
+%!assert(size (cauchy_rnd (1, 2*ones(2,1))), [2, 1]);
+%!assert(size (cauchy_rnd (1, 2*ones(2,2))), [2, 2]);
+%!assert(size (cauchy_rnd (1, 2, 3)), [3, 3]);
+%!assert(size (cauchy_rnd (1, 2, [4 1])), [4, 1]);
+%!assert(size (cauchy_rnd (1, 2, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (cauchy_rnd (1, 2)), "double");
+%!assert(class (cauchy_rnd (single(1), 2)), "single");
+%!assert(class (cauchy_rnd (single([1 1]), 2)), "single");
+%!assert(class (cauchy_rnd (1, single(2))), "single");
+%!assert(class (cauchy_rnd (1, single([2 2]))), "single");
+
+%% Test input validation
+%!error cauchy_rnd ()
+%!error cauchy_rnd (1)
+%!error cauchy_rnd (ones(3),ones(2))
+%!error cauchy_rnd (ones(2),ones(3))
+%!error cauchy_rnd (i, 2)
+%!error cauchy_rnd (2, i)
+%!error cauchy_rnd (1,2, -1)
+%!error cauchy_rnd (1,2, ones(2))
+%!error cauchy_rnd (1,2, [2 -1 2])
+%!error cauchy_rnd (1,2, 1, ones(2))
+%!error cauchy_rnd (1,2, 1, -1)
+%!error cauchy_rnd (ones(2,2), 2, 3)
+%!error cauchy_rnd (ones(2,2), 2, [3, 2])
+%!error cauchy_rnd (ones(2,2), 2, 2, 3)
+
--- a/scripts/statistics/distributions/chi2cdf.m
+++ b/scripts/statistics/distributions/chi2cdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -19,7 +20,7 @@
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} chi2cdf (@var{x}, @var{n})
 ## For each element of @var{x}, compute the cumulative distribution
-## function (CDF) at @var{x} of the chisquare distribution with @var{n}
+## function (CDF) at @var{x} of the chi-square distribution with @var{n}
 ## degrees of freedom.
 ## @end deftypefn
 
@@ -35,10 +36,38 @@
   if (!isscalar (n))
     [retval, x, n] = common_size (x, n);
     if (retval > 0)
-      error ("chi2cdf: X and N must be of common size or scalar");
+      error ("chi2cdf: X and N must be of common size or scalars");
     endif
   endif
 
-  cdf = gamcdf (x, n / 2, 2);
+  if (iscomplex (x) || iscomplex (n))
+    error ("chi2cdf: X and N must not be complex");
+  endif
+
+  cdf = gamcdf (x, n/2, 2);
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 0.5 1 2];
+%! y = [0, 1 - exp(-x(2:end)/2)];
+%!assert(chi2cdf (x, 2*ones(1,5)), y, eps);
+%!assert(chi2cdf (x, 2), y, eps);
+%!assert(chi2cdf (x, 2*[1 0 NaN 1 1]), [y(1) NaN NaN y(4:5)], eps);
+%!assert(chi2cdf ([x(1:2) NaN x(4:5)], 2), [y(1:2) NaN y(4:5)], eps);
+
+%% Test class of input preserved
+%!assert(chi2cdf ([x, NaN], 2), [y, NaN], eps);
+%!assert(chi2cdf (single([x, NaN]), 2), single([y, NaN]), eps("single"));
+%!assert(chi2cdf ([x, NaN], single(2)), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error chi2cdf ()
+%!error chi2cdf (1)
+%!error chi2cdf (1,2,3)
+%!error chi2cdf (ones(3),ones(2))
+%!error chi2cdf (ones(2),ones(3))
+%!error chi2cdf (i, 2)
+%!error chi2cdf (2, i)
+
--- a/scripts/statistics/distributions/chi2inv.m
+++ b/scripts/statistics/distributions/chi2inv.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -19,7 +20,7 @@
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} chi2inv (@var{x}, @var{n})
 ## For each element of @var{x}, compute the quantile (the inverse of the
-## CDF) at @var{x} of the chisquare distribution with @var{n} degrees of
+## CDF) at @var{x} of the chi-square distribution with @var{n} degrees of
 ## freedom.
 ## @end deftypefn
 
@@ -35,10 +36,37 @@
   if (!isscalar (n))
     [retval, x, n] = common_size (x, n);
     if (retval > 0)
-      error ("chi2inv: X and N must be of common size or scalar");
+      error ("chi2inv: X and N must be of common size or scalars");
     endif
   endif
 
-  inv = gaminv (x, n / 2, 2);
+  if (iscomplex (x) || iscomplex (n))
+    error ("chi2inv: X and N must not be complex");
+  endif
+
+  inv = gaminv (x, n/2, 2);
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.3934693402873666 1 2];
+%!assert(chi2inv (x, 2*ones(1,5)), [NaN 0 1 Inf NaN], 5*eps);
+%!assert(chi2inv (x, 2), [NaN 0 1 Inf NaN], 5*eps);
+%!assert(chi2inv (x, 2*[0 1 NaN 1 1]), [NaN 0 NaN Inf NaN], 5*eps);
+%!assert(chi2inv ([x(1:2) NaN x(4:5)], 2), [NaN 0 NaN Inf NaN], 5*eps);
+
+%% Test class of input preserved
+%!assert(chi2inv ([x, NaN], 2), [NaN 0 1 Inf NaN NaN], 5*eps);
+%!assert(chi2inv (single([x, NaN]), 2), single([NaN 0 1 Inf NaN NaN]), 5*eps("single"));
+%!assert(chi2inv ([x, NaN], single(2)), single([NaN 0 1 Inf NaN NaN]), 5*eps("single"));
+
+%% Test input validation
+%!error chi2inv ()
+%!error chi2inv (1)
+%!error chi2inv (1,2,3)
+%!error chi2inv (ones(3),ones(2))
+%!error chi2inv (ones(2),ones(3))
+%!error chi2inv (i, 2)
+%!error chi2inv (2, i)
+
--- a/scripts/statistics/distributions/chi2pdf.m
+++ b/scripts/statistics/distributions/chi2pdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -19,7 +20,7 @@
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} chi2pdf (@var{x}, @var{n})
 ## For each element of @var{x}, compute the probability density function
-## (PDF) at @var{x} of the chisquare distribution with @var{n} degrees
+## (PDF) at @var{x} of the chi-square distribution with @var{n} degrees
 ## of freedom.
 ## @end deftypefn
 
@@ -35,10 +36,37 @@
   if (!isscalar (n))
     [retval, x, n] = common_size (x, n);
     if (retval > 0)
-      error ("chi2pdf: X and N must be of common size or scalar");
+      error ("chi2pdf: X and N must be of common size or scalars");
     endif
   endif
 
-  pdf = gampdf (x, n / 2, 2);
+  if (iscomplex (x) || iscomplex (n))
+    error ("chi2pdf: X and N must not be complex");
+  endif
+
+  pdf = gampdf (x, n/2, 2);
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 0.5 1 Inf];
+%! y = [0, 1/2 * exp(-x(2:5)/2)];
+%!assert(chi2pdf (x, 2*ones(1,5)), y);
+%!assert(chi2pdf (x, 2), y);
+%!assert(chi2pdf (x, 2*[1 0 NaN 1 1]), [y(1) NaN NaN y(4:5)]);
+%!assert(chi2pdf ([x, NaN], 2), [y, NaN]);
+
+%% Test class of input preserved
+%!assert(chi2pdf (single([x, NaN]), 2), single([y, NaN]));
+%!assert(chi2pdf ([x, NaN], single(2)), single([y, NaN]));
+
+%% Test input validation
+%!error chi2pdf ()
+%!error chi2pdf (1)
+%!error chi2pdf (1,2,3)
+%!error chi2pdf (ones(3),ones(2))
+%!error chi2pdf (ones(2),ones(3))
+%!error chi2pdf (i, 2)
+%!error chi2pdf (2, i)
+
--- a/scripts/statistics/distributions/chi2rnd.m
+++ b/scripts/statistics/distributions/chi2rnd.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,75 +18,103 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} chi2rnd (@var{n}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} chi2rnd (@var{n}, @var{sz})
-## Return an @var{r} by @var{c}  or a @code{size (@var{sz})} matrix of
-## random samples from the chisquare distribution with @var{n} degrees
-## of freedom.  @var{n} must be a scalar or of size @var{r} by @var{c}.
+## @deftypefn  {Function File} {} chi2rnd (@var{n})
+## @deftypefnx {Function File} {} chi2rnd (@var{n}, @var{r})
+## @deftypefnx {Function File} {} chi2rnd (@var{n}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} chi2rnd (@var{n}, [@var{sz}])
+## Return a matrix of random samples from the chi-square distribution with
+## @var{n} degrees of freedom.
 ##
-## If @var{r} and @var{c} are omitted, the size of the result matrix is
-## the size of @var{n}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the size of
+## @var{n}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the chi-square distribution
 
-function rnd = chi2rnd (n, r, c)
-
-  if (nargin == 3)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("chi2rnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("chi2rnd: C must be a positive integer");
-    endif
-    sz = [r, c];
+function rnd = chi2rnd (n, varargin)
 
-    if (any (size (n) != 1)
-        && (length (size (n)) != length (sz) || any (size (n) != sz)))
-      error ("chi2rnd: N must be scalar or of size [R, C]");
-    endif
-  elseif (nargin == 2)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
-    else
-      error ("chi2rnd: R must be a positive integer or vector");
-    endif
-
-    if (any (size (n) != 1)
-        && (length (size (n)) != length (sz) || any (size (n) != sz)))
-      error ("chi2rnd: N must be scalar or of size SZ");
-    endif
-  elseif (nargin == 1)
-    sz = size(n);
-  else
+  if (nargin < 1)
     print_usage ();
   endif
 
-  if (isscalar (n))
-     if (find (!(n > 0) | !(n < Inf)))
-       rnd = NaN (sz);
-     else
-       rnd = 2 * randg(n/2, sz);
-     endif
-  else
-    [retval, n, dummy] = common_size (n, ones (sz));
-    if (retval > 0)
-      error ("chi2rnd: a and b must be of common size or scalar");
+  if (nargin == 1)
+    sz = size (n);
+  elseif (nargin == 2)
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
+    else
+      error ("chi2rnd: dimension vector must be row vector of non-negative integers");
+    endif
+  elseif (nargin > 2)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("chi2rnd: dimensions must be non-negative integers");
     endif
+    sz = [varargin{:}];
+  endif
 
-    rnd = zeros (sz);
-    k = find (!(n > 0) | !(n < Inf));
-    if (any (k))
-      rnd(k) = NaN;
+  if (!isscalar (n) && !isequal (size (n), sz))
+    error ("chi2rnd: N must be scalar or of size SZ");
+  endif
+
+  if (iscomplex (n))
+    error ("chi2rnd: N must not be complex");
+  endif
+
+  if (isa (n, "single"))
+    cls = "single";
+  else
+    cls = "double";
+  endif
+
+  if (isscalar (n))
+    if ((n > 0) && (n < Inf))
+      rnd = 2 * randg (n/2, sz);
+      if (strcmp (cls, "single"))
+        rnd = single (rnd);
+      endif
+    else
+      rnd = NaN (sz, cls);
     endif
+  else
+    rnd = NaN (sz, cls);
 
-    k = find ((n > 0) & (n < Inf));
-    if (any (k))
-      rnd(k) = 2 * randg(n(k)/2, size(k));
-    endif
+    k = (n > 0) | (n < Inf);
+    rnd(k) = 2 * randg (n(k)/2);
   endif
 
 endfunction
+
+
+%!assert(size (chi2rnd (2)), [1, 1]);
+%!assert(size (chi2rnd (ones(2,1))), [2, 1]);
+%!assert(size (chi2rnd (ones(2,2))), [2, 2]);
+%!assert(size (chi2rnd (1, 3)), [3, 3]);
+%!assert(size (chi2rnd (1, [4 1])), [4, 1]);
+%!assert(size (chi2rnd (1, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (chi2rnd (2)), "double");
+%!assert(class (chi2rnd (single(2))), "single");
+%!assert(class (chi2rnd (single([2 2]))), "single");
+
+%% Test input validation
+%!error chi2rnd ()
+%!error chi2rnd (ones(3),ones(2))
+%!error chi2rnd (ones(2),ones(3))
+%!error chi2rnd (i)
+%!error chi2rnd (1, -1)
+%!error chi2rnd (1, ones(2))
+%!error chi2rnd (1, [2 -1 2])
+%!error chi2rnd (ones(2,2), 3)
+%!error chi2rnd (ones(2,2), [3, 2])
+%!error chi2rnd (ones(2,2), 2, 3)
+
--- a/scripts/statistics/distributions/discrete_cdf.m
+++ b/scripts/statistics/distributions/discrete_cdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 2010-2011 David Bateman
 ##
 ## This file is part of Octave.
@@ -29,28 +30,52 @@
     print_usage ();
   endif
 
-  sz = size (x);
-
   if (! isvector (v))
     error ("discrete_cdf: V must be a vector");
+  elseif (any (isnan (v)))
+    error ("discrete_cdf: V must not have any NaN elements");
   elseif (! isvector (p) || (length (p) != length (v)))
     error ("discrete_cdf: P must be a vector with length (V) elements");
   elseif (! (all (p >= 0) && any (p)))
-    error ("discrete_cdf: P must be a nonzero, nonnegative vector");
+    error ("discrete_cdf: P must be a nonzero, non-negative vector");
+  endif
+
+  p = p(:) / sum (p);   # Reshape and normalize probability vector
+
+  if (isa (x, "single") || isa (v, "single") || isa (p, "single"));
+    cdf = NaN (size (x), "single");
+  else
+    cdf = NaN (size (x));
   endif
 
-  n = numel (x);
-  m = length (v);
-  x = reshape (x, n, 1);
-  v = reshape (v, 1, m);
-  p = reshape (p / sum (p), m, 1);
-
-  cdf = NaN (sz);
-  k = find (!isnan (x));
-  if (any (k))
-    n = length (k);
-    [vs, vi] = sort (v);
-    cdf(k) = [0 ; cumsum(p(vi))](lookup (vs, x(k)) + 1);
-  endif
+  k = !isnan (x);
+  [vs, vi] = sort (v);
+  cdf(k) = [0 ; cumsum(p(vi))](lookup (vs, x(k)) + 1);
 
 endfunction
+
+
+%!shared x,v,p,y
+%! x = [-1 0.1 1.1 1.9 3];
+%! v = 0.1:0.2:1.9;
+%! p = 1/length(v) * ones(1, length(v));
+%! y = [0 0.1 0.6 1 1];
+%!assert(discrete_cdf ([x, NaN], v, p), [y, NaN], eps);
+
+%% Test class of input preserved
+%!assert(discrete_cdf (single([x, NaN]), v, p), single([y, NaN]), 2*eps("single"));
+%!assert(discrete_cdf ([x, NaN], single(v), p), single([y, NaN]), 2*eps("single"));
+%!assert(discrete_cdf ([x, NaN], v, single(p)), single([y, NaN]), 2*eps("single"));
+
+%% Test input validation
+%!error discrete_cdf ()
+%!error discrete_cdf (1)
+%!error discrete_cdf (1,2)
+%!error discrete_cdf (1,2,3,4)
+%!error discrete_cdf (1, ones(2), ones(2,1))
+%!error discrete_cdf (1, [1 ; NaN], ones(2,1))
+%!error discrete_cdf (1, ones(2,1), ones(1,1))
+%!error discrete_cdf (1, ones(2,1), [1 -1])
+%!error discrete_cdf (1, ones(2,1), [1 NaN])
+%!error discrete_cdf (1, ones(2,1), [0  0])
+
--- a/scripts/statistics/distributions/discrete_inv.m
+++ b/scripts/statistics/distributions/discrete_inv.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1996-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,7 +19,7 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} discrete_inv (@var{x}, @var{v}, @var{p})
-## For each component of @var{x}, compute the quantile (the inverse of
+## For each element of @var{x}, compute the quantile (the inverse of
 ## the CDF) at @var{x} of the univariate distribution which assumes the
 ## values in @var{v} with probabilities @var{p}.
 ## @end deftypefn
@@ -32,35 +33,63 @@
     print_usage ();
   endif
 
-  sz = size (x);
-
   if (! isvector (v))
     error ("discrete_inv: V must be a vector");
   elseif (! isvector (p) || (length (p) != length (v)))
     error ("discrete_inv: P must be a vector with length (V) elements");
+  elseif (any (isnan (p)))
+    error ("discrete_rnd: P must not have any NaN elements");
   elseif (! (all (p >= 0) && any (p)))
-    error ("discrete_inv: P must be a nonzero, nonnegative vector");
+    error ("discrete_inv: P must be a nonzero, non-negative vector");
+  endif
+
+  if (isa (x, "single") || isa (v, "single") || isa (p, "single"));
+    inv = NaN (size (x), "single");
+  else
+    inv = NaN (size (x));
   endif
 
-  n = numel (x);
-  x = reshape (x, 1, n);
-  m = length (v);
-  [v, idx] = sort (v);
-  p = reshape (cumsum (p (idx) / sum (p)), m, 1);
-
-  inv = NaN (sz);
-  if (any (k = find (x == 0)))
-    inv(k) = -Inf;
-  endif
-  if (any (k = find (x == 1)))
-    inv(k) = v(m) * ones (size (k));
+  ## FIXME: This isn't elegant.  But cumsum and lookup together produce
+  ## different results when called with a single or a double.
+  if (isa (p, "single"));
+    p = double (p);
   endif
 
-  if (any (k = find ((x > 0) & (x < 1))))
-    n = length (k);
-    inv (k) = v(length (p) - lookup (sort (p,"descend"), x(k)) + 1);
-  endif
+  [v, idx] = sort (v);
+  p = cumsum (p(idx)(:)) / sum (p);  # Reshape and normalize probability vector
+
+  k = (x == 0);
+  inv(k) = v(1);
+
+  k = (x == 1);
+  inv(k) = v(end);
+
+  k = (x > 0) & (x < 1);
+  inv(k) = v(length (p) - lookup (sort (p, "descend"), x(k)) + 1);
 
 endfunction
 
 
+%!shared x,v,p,y
+%! x = [-1 0 0.1 0.5 1 2];
+%! v = 0.1:0.2:1.9;
+%! p = 1/length(v) * ones(1, length(v));
+%! y = [NaN v(1) v(1) v(end/2) v(end) NaN];
+%!assert(discrete_inv ([x, NaN], v, p), [y, NaN], eps);
+
+%% Test class of input preserved
+%!assert(discrete_inv (single([x, NaN]), v, p), single([y, NaN]), eps("single"));
+%!assert(discrete_inv ([x, NaN], single(v), p), single([y, NaN]), eps("single"));
+%!assert(discrete_inv ([x, NaN], v, single(p)), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error discrete_inv ()
+%!error discrete_inv (1)
+%!error discrete_inv (1,2)
+%!error discrete_inv (1,2,3,4)
+%!error discrete_inv (1, ones(2), ones(2,1))
+%!error discrete_inv (1, ones(2,1), ones(1,1))
+%!error discrete_inv (1, ones(2,1), [1 NaN])
+%!error discrete_inv (1, ones(2,1), [1 -1])
+%!error discrete_inv (1, ones(2,1), [0  0])
+
--- a/scripts/statistics/distributions/discrete_pdf.m
+++ b/scripts/statistics/distributions/discrete_pdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1996-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -24,7 +25,7 @@
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
-## Description: pDF of a discrete distribution
+## Description: PDF of a discrete distribution
 
 function pdf = discrete_pdf (x, v, p)
 
@@ -32,28 +33,53 @@
     print_usage ();
   endif
 
-  sz = size (x);
-
   if (! isvector (v))
     error ("discrete_pdf: V must be a vector");
+  elseif (any (isnan (v)))
+    error ("discrete_pdf: V must not have any NaN elements");
   elseif (! isvector (p) || (length (p) != length (v)))
     error ("discrete_pdf: P must be a vector with length (V) elements");
   elseif (! (all (p >= 0) && any (p)))
-    error ("discrete_pdf: P must be a nonzero, nonnegative vector");
+    error ("discrete_pdf: P must be a nonzero, non-negative vector");
+  endif
+
+  ## Reshape and normalize probability vector.  Values not in table get 0 prob.
+  p = [0 ; p(:)/sum(p)];   
+
+  if (isa (x, "single") || isa (v, "single") || isa (p, "single"))
+    pdf = NaN (size (x), "single");
+  else
+    pdf = NaN (size (x));
   endif
 
-  n = numel (x);
-  m = length (v);
-  x = reshape (x, n, 1);
-  v = reshape (v, 1, m);
-  p = reshape (p / sum (p), m, 1);
-
-  pdf = NaN (sz);
-  k = find (!isnan (x));
-  if (any (k))
-    n = length (k);
-    [vs, vi] = sort (v);
-    pdf (k) = p (vi(lookup (vs, x(k), 'm')));
-  endif
+  k = !isnan (x);
+  [vs, vi] = sort (v(:));
+  pdf(k) = p([0 ; vi](lookup (vs, x(k), 'm') + 1) + 1);
 
 endfunction
+
+
+%!shared x,v,p,y
+%! x = [-1 0.1 1.1 1.9 3];
+%! v = 0.1:0.2:1.9;
+%! p = 1/length(v) * ones(1, length(v));
+%! y = [0 0.1 0.1 0.1 0];
+%!assert(discrete_pdf ([x, NaN], v, p), [y, NaN], 5*eps);
+
+%% Test class of input preserved
+%!assert(discrete_pdf (single([x, NaN]), v, p), single([y, NaN]), 5*eps("single"));
+%!assert(discrete_pdf ([x, NaN], single(v), p), single([y, NaN]), 5*eps("single"));
+%!assert(discrete_pdf ([x, NaN], v, single(p)), single([y, NaN]), 5*eps("single"));
+
+%% Test input validation
+%!error discrete_pdf ()
+%!error discrete_pdf (1)
+%!error discrete_pdf (1,2)
+%!error discrete_pdf (1,2,3,4)
+%!error discrete_pdf (1, ones(2), ones(2,1))
+%!error discrete_pdf (1, [1 ; NaN], ones(2,1))
+%!error discrete_pdf (1, ones(2,1), ones(1,1))
+%!error discrete_pdf (1, ones(2,1), [1 -1])
+%!error discrete_pdf (1, ones(2,1), [1 NaN])
+%!error discrete_pdf (1, ones(2,1), [0  0])
+
--- a/scripts/statistics/distributions/discrete_rnd.m
+++ b/scripts/statistics/distributions/discrete_rnd.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1996-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,51 +18,29 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} discrete_rnd (@var{n}, @var{v}, @var{p})
-## @deftypefnx {Function File} {} discrete_rnd (@var{v}, @var{p}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} discrete_rnd (@var{v}, @var{p}, @var{sz})
-## Generate a row vector containing a random sample of size @var{n} from
-## the univariate distribution which assumes the values in @var{v} with
-## probabilities @var{p}.  @var{n} must be a scalar.
+## @deftypefn  {Function File} {} discrete_rnd (@var{v}, @var{p})
+## @deftypefnx {Function File} {} discrete_rnd (@var{v}, @var{p}, @var{r})
+## @deftypefnx {Function File} {} discrete_rnd (@var{v}, @var{p}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} discrete_rnd (@var{v}, @var{p}, [@var{sz}])
+## Return a matrix of random samples from the univariate distribution which
+## assumes the values in @var{v} with probabilities @var{p}.
 ##
-## If @var{r} and @var{c} are given create a matrix with @var{r} rows and
-## @var{c} columns.  Or if @var{sz} is a vector, create a matrix of size
-## @var{sz}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the common size of
+## @var{v} and @var{p}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from a discrete distribution
 
-function rnd = discrete_rnd (v, p, r, c)
+function rnd = discrete_rnd (v, p, varargin)
 
-  if (nargin == 4)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("discrete_rnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("discrete_rnd: C must be a positive integer");
-    endif
-    sz = [r, c];
-  elseif (nargin == 3)
-    ## A potential problem happens here if all args are scalar, as
-    ## we can't distiguish between the command syntax. Thankfully this
-    ## case doesn't make much sense. So we assume the first syntax
-    ## if the first arg is scalar
-
-    if (isscalar (v))
-      sz = [1, floor(v)];
-      v = p;
-      p = r;
-    else
-      if (isscalar (r) && (r > 0))
-        sz = [r, r];
-      elseif (isvector(r) && all (r > 0))
-        sz = r(:)';
-      else
-        error ("discrete_rnd: R must be a positive integer or vector");
-      endif
-    endif
-  else
+  if (nargin < 2)
     print_usage ();
   endif
 
@@ -69,9 +48,57 @@
     error ("discrete_rnd: V must be a vector");
   elseif (! isvector (p) || (length (p) != length (v)))
     error ("discrete_rnd: P must be a vector with length (V) elements");
+  elseif (any (isnan (p)))
+    error ("discrete_rnd: P must not have any NaN elements");
   elseif (! (all (p >= 0) && any (p)))
-    error ("discrete_rnd: P must be a nonzero, nonnegative vector");
+    error ("discrete_rnd: P must be a nonzero, non-negative vector");
+  endif
+
+  if (nargin == 2)
+    sz = size (v);
+  elseif (nargin == 3)
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
+    else
+      error ("discrete_rnd: dimension vector must be row vector of non-negative integers");
+    endif
+  elseif (nargin > 3)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("discrete_rnd: dimensions must be non-negative integers");
+    endif
+    sz = [varargin{:}];
   endif
 
-  rnd = v (lookup (cumsum (p (1 : end-1)) / sum(p), rand (sz)) + 1);
+  rnd = v(lookup (cumsum (p(1:end-1)) / sum (p), rand (sz)) + 1);
+  rnd = reshape (rnd, sz);
+
 endfunction
+
+
+%!assert(size (discrete_rnd (1:2, 1:2, 3)), [3, 3]);
+%!assert(size (discrete_rnd (1:2, 1:2, [4 1])), [4, 1]);
+%!assert(size (discrete_rnd (1:2, 1:2, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (discrete_rnd (1:2, 1:2)), "double");
+%!assert(class (discrete_rnd (single(1:2), 1:2)), "single");
+## FIXME: Maybe this should work, maybe it shouldn't.
+#%!assert(class (discrete_rnd (1:2, single(1:2))), "single");
+
+%% Test input validation
+%!error discrete_rnd ()
+%!error discrete_rnd (1)
+%!error discrete_rnd (1:2,1:2, -1)
+%!error discrete_rnd (1:2,1:2, ones(2))
+%!error discrete_rnd (1:2,1:2, [2 -1 2])
+%!error discrete_rnd (1:2,1:2, 1, ones(2))
+%!error discrete_rnd (1:2,1:2, 1, -1)
+%% test v,p verification
+%!error discrete_rnd (1, ones(2), ones(2,1))
+%!error discrete_rnd (1, ones(2,1), ones(1,1))
+%!error discrete_rnd (1, ones(2,1), [1 -1])
+%!error discrete_rnd (1, ones(2,1), [1 NaN])
+%!error discrete_rnd (1, ones(2,1), [0  0])
+
--- a/scripts/statistics/distributions/empirical_cdf.m
+++ b/scripts/statistics/distributions/empirical_cdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1996-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -36,6 +37,26 @@
     error ("empirical_cdf: DATA must be a vector");
   endif
 
-  cdf = discrete_cdf (x, data, ones (size (data)) / length (data));
+  cdf = discrete_cdf (x, data, ones (size (data)));
 
 endfunction
+
+
+%!shared x,v,y
+%! x = [-1 0.1 1.1 1.9 3];
+%! v = 0.1:0.2:1.9;
+%! y = [0 0.1 0.6 1 1];
+%!assert(empirical_cdf (x, v), y, eps);
+%!assert(empirical_cdf ([x(1) NaN x(3:5)], v), [0 NaN 0.6 1 1], eps);
+
+%% Test class of input preserved
+%!assert(empirical_cdf ([x, NaN], v), [y, NaN], eps);
+%!assert(empirical_cdf (single([x, NaN]), v), single([y, NaN]), eps);
+%!assert(empirical_cdf ([x, NaN], single(v)), single([y, NaN]), eps);
+
+%% Test input validation
+%!error empirical_cdf ()
+%!error empirical_cdf (1)
+%!error empirical_cdf (1,2,3)
+%!error empirical_cdf (1, ones(2))
+
--- a/scripts/statistics/distributions/empirical_inv.m
+++ b/scripts/statistics/distributions/empirical_inv.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1996-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -36,6 +37,25 @@
     error ("empirical_inv: DATA must be a vector");
   endif
 
-  inv = discrete_inv (x, data, ones (size (data)) / length (data));
+  inv = discrete_inv (x, data, ones (size (data)));
 
 endfunction
+
+
+%!shared x,v,y
+%! x = [-1 0 0.1 0.5 1 2];
+%! v = 0.1:0.2:1.9;
+%! y = [NaN v(1) v(1) v(end/2) v(end) NaN];
+%!assert(empirical_inv (x, v), y, eps);
+
+%% Test class of input preserved
+%!assert(empirical_inv ([x, NaN], v), [y, NaN], eps);
+%!assert(empirical_inv (single([x, NaN]), v), single([y, NaN]), eps);
+%!assert(empirical_inv ([x, NaN], single(v)), single([y, NaN]), eps);
+
+%% Test input validation
+%!error empirical_inv ()
+%!error empirical_inv (1)
+%!error empirical_inv (1,2,3)
+%!error empirical_inv (1, ones(2))
+
--- a/scripts/statistics/distributions/empirical_pdf.m
+++ b/scripts/statistics/distributions/empirical_pdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1996-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -36,6 +37,24 @@
     error ("empirical_pdf: DATA must be a vector");
   endif
 
-  pdf = discrete_pdf (x, data, ones (size (data)) / length (data));
+  pdf = discrete_pdf (x, data, ones (size (data)));
 
 endfunction
+
+
+%!shared x,v,y
+%! x = [-1 0.1 1.1 1.9 3];
+%! v = 0.1:0.2:1.9;
+%! y = [0 0.1 0.1 0.1 0];
+%!assert(empirical_pdf (x, v), y);
+
+%% Test class of input preserved
+%!assert(empirical_pdf (single(x), v), single (y));
+%!assert(empirical_pdf (x, single(v)), single (y));
+
+%% Test input validation
+%!error empirical_pdf ()
+%!error empirical_pdf (1)
+%!error empirical_pdf (1,2,3)
+%!error empirical_inv (1, ones(2))
+
--- a/scripts/statistics/distributions/empirical_rnd.m
+++ b/scripts/statistics/distributions/empirical_rnd.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1996-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,29 +18,29 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} empirical_rnd (@var{n}, @var{data})
-## @deftypefnx {Function File} {} empirical_rnd (@var{data}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} empirical_rnd (@var{data}, @var{sz})
-## Generate a bootstrap sample of size @var{n} from the empirical
-## distribution obtained from the univariate sample @var{data}.
+## @deftypefn  {Function File} {} empirical_rnd (@var{data})
+## @deftypefnx {Function File} {} empirical_rnd (@var{data}, @var{r})
+## @deftypefnx {Function File} {} empirical_rnd (@var{data}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} empirical_rnd (@var{data}, [@var{sz}])
+## Return a matrix of random samples from the empirical distribution obtained
+## from the univariate sample @var{data}.
 ##
-## If @var{r} and @var{c} are given create a matrix with @var{r} rows and
-## @var{c} columns.  Or if @var{sz} is a vector, create a matrix of size
-## @var{sz}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is a random ordering
+## of the sample @var{data}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Bootstrap samples from the empirical distribution
 
-function rnd = empirical_rnd (data, r, c)
+function rnd = empirical_rnd (data, varargin)
 
-  if (nargin == 2)
-    if (isscalar(data))
-      c = data;
-      data = r;
-      r = 1;
-    endif
-  elseif (nargin != 3)
+  if (nargin < 1)
     print_usage ();
   endif
 
@@ -47,6 +48,22 @@
     error ("empirical_rnd: DATA must be a vector");
   endif
 
-  rnd = discrete_rnd (data, ones (size (data)) / length (data), r, c);
+  rnd = discrete_rnd (data, ones (size (data)), varargin{:});
 
 endfunction
+
+
+%!assert(size (empirical_rnd (ones (3, 1))), [3, 1]);
+%!assert(size (empirical_rnd (1:2, [4 1])), [4, 1]);
+%!assert(size (empirical_rnd (1:2, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (empirical_rnd (1:2, 1)), "double");
+%!assert(class (empirical_rnd (single(1:2), 1)), "single");
+
+%% Test input validation
+%!error empirical_rnd ()
+%!error empirical_rnd (ones(2), 1)
+%% test data verification
+%!error empirical_rnd (ones(2), 1, 1)
+
--- a/scripts/statistics/distributions/expcdf.m
+++ b/scripts/statistics/distributions/expcdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -22,7 +23,7 @@
 ## function (CDF) at @var{x} of the exponential distribution with
 ## mean @var{lambda}.
 ##
-## The arguments can be of common size or scalar.
+## The arguments can be of common size or scalars.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -34,40 +35,57 @@
     print_usage ();
   endif
 
-  if (!isscalar (x) && !isscalar(lambda))
+  if (!isscalar (lambda))
     [retval, x, lambda] = common_size (x, lambda);
     if (retval > 0)
-      error ("expcdf: X and LAMBDA must be of common size or scalar");
+      error ("expcdf: X and LAMBDA must be of common size or scalars");
     endif
   endif
 
-  if (isscalar (x))
-    sz = size (lambda);
-  else
-    sz = size (x);
+  if (iscomplex (x) || iscomplex (lambda))
+    error ("expcdf: X and LAMBDA must not be complex");
   endif
 
-  cdf = zeros (sz);
-
-  k = find (isnan (x) | !(lambda > 0));
-  if (any (k))
-    cdf(k) = NaN;
+  if (isa (x, "single") || isa (lambda, "single"))
+    cdf = zeros (size (x), "single");
+  else
+    cdf = zeros (size (x));
   endif
 
-  k = find ((x == Inf) & (lambda > 0));
-  if (any (k))
-    cdf(k) = 1;
-  endif
+  k = isnan (x) | !(lambda > 0);
+  cdf(k) = NaN;
+
+  k = (x == Inf) & (lambda > 0);
+  cdf(k) = 1;
 
-  k = find ((x > 0) & (x < Inf) & (lambda > 0));
-  if (any (k))
-    if isscalar (lambda)
-      cdf (k) = 1 - exp (- x(k) ./ lambda);
-    elseif isscalar (x)
-      cdf (k) = 1 - exp (- x ./ lambda(k));
-    else
-      cdf (k) = 1 - exp (- x(k) ./ lambda(k));
-    endif
+  k = (x > 0) & (x < Inf) & (lambda > 0);
+  if isscalar (lambda)
+    cdf(k) = 1 - exp (- x(k) / lambda);
+  else
+    cdf(k) = 1 - exp (- x(k) ./ lambda(k));
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 0.5 1 Inf];
+%! y = [0, 1 - exp(-x(2:end)/2)];
+%!assert(expcdf (x, 2*ones(1,5)), y);
+%!assert(expcdf (x, 2), y);
+%!assert(expcdf (x, 2*[1 0 NaN 1 1]), [y(1) NaN NaN y(4:5)]);
+
+%% Test class of input preserved
+%!assert(expcdf ([x, NaN], 2), [y, NaN]);
+%!assert(expcdf (single([x, NaN]), 2), single([y, NaN]));
+%!assert(expcdf ([x, NaN], single(2)), single([y, NaN]));
+
+%% Test input validation
+%!error expcdf ()
+%!error expcdf (1)
+%!error expcdf (1,2,3)
+%!error expcdf (ones(3),ones(2))
+%!error expcdf (ones(2),ones(3))
+%!error expcdf (i, 2)
+%!error expcdf (2, i)
+
--- a/scripts/statistics/distributions/expinv.m
+++ b/scripts/statistics/distributions/expinv.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -19,8 +20,7 @@
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} expinv (@var{x}, @var{lambda})
 ## For each element of @var{x}, compute the quantile (the inverse of the
-## CDF) at @var{x} of the exponential distribution with mean
-## @var{lambda}.
+## CDF) at @var{x} of the exponential distribution with mean @var{lambda}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -32,41 +32,64 @@
     print_usage ();
   endif
 
-  if (!isscalar (x) && !isscalar(lambda))
+  if (!isscalar (lambda))
     [retval, x, lambda] = common_size (x, lambda);
     if (retval > 0)
-      error ("expinv: X and LAMBDA must be of common size or scalar");
+      error ("expinv: X and LAMBDA must be of common size or scalars");
     endif
   endif
 
-  if (isscalar (x))
-    sz = size (lambda);
-  else
-    sz = size (x);
+  if (iscomplex (x) || iscomplex (lambda))
+    error ("expinv: X and LAMBDA must not be complex");
   endif
 
-  inv = zeros (sz);
+  if (!isscalar (x))
+    sz = size (x);
+  else
+    sz = size (lambda);
+  endif
 
-  k = find (!(lambda > 0) | (x < 0) | (x > 1) | isnan (x));
-  if (any (k))
-    inv(k) = NaN;
+  if (iscomplex (x) || iscomplex (lambda))
+    error ("expinv: X and LAMBDA must not be complex");
   endif
 
-  k = find ((x == 1) & (lambda > 0));
-  if (any (k))
-    inv(k) = Inf;
+  if (isa (x, "single") || isa (lambda, "single"))
+    inv = NaN (size (x), "single");
+  else
+    inv = NaN (size (x));
   endif
 
-  k = find ((x > 0) & (x < 1) & (lambda > 0));
-  if (any (k))
-    if isscalar (lambda)
-      inv(k) = - lambda .* log (1 - x(k));
-    elseif isscalar (x)
-      inv(k) = - lambda(k) .* log (1 - x);
-    else
-      inv(k) = - lambda(k) .* log (1 - x(k));
-    endif
+  k = (x == 1) & (lambda > 0);
+  inv(k) = Inf;
+
+  k = (x >= 0) & (x < 1) & (lambda > 0);
+  if isscalar (lambda)
+    inv(k) = - lambda * log (1 - x(k));
+  else
+    inv(k) = - lambda(k) .* log (1 - x(k));
   endif
 
 endfunction
 
+
+%!shared x
+%! x = [-1 0 0.3934693402873666 1 2];
+%!assert(expinv (x, 2*ones(1,5)), [NaN 0 1 Inf NaN], eps);
+%!assert(expinv (x, 2), [NaN 0 1 Inf NaN], eps);
+%!assert(expinv (x, 2*[1 0 NaN 1 1]), [NaN NaN NaN Inf NaN], eps);
+%!assert(expinv ([x(1:2) NaN x(4:5)], 2), [NaN 0 NaN Inf NaN], eps);
+
+%% Test class of input preserved
+%!assert(expinv ([x, NaN], 2), [NaN 0 1 Inf NaN NaN], eps);
+%!assert(expinv (single([x, NaN]), 2), single([NaN 0 1 Inf NaN NaN]), eps);
+%!assert(expinv ([x, NaN], single(2)), single([NaN 0 1 Inf NaN NaN]), eps);
+
+%% Test input validation
+%!error expinv ()
+%!error expinv (1)
+%!error expinv (1,2,3)
+%!error expinv (ones(3),ones(2))
+%!error expinv (ones(2),ones(3))
+%!error expinv (i, 2)
+%!error expinv (2, i)
+
--- a/scripts/statistics/distributions/exppdf.m
+++ b/scripts/statistics/distributions/exppdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -19,7 +20,7 @@
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} exppdf (@var{x}, @var{lambda})
 ## For each element of @var{x}, compute the probability density function
-## (PDF) of the exponential distribution with mean @var{lambda}.
+## (PDF) at @var{x} of the exponential distribution with mean @var{lambda}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -31,34 +32,53 @@
     print_usage ();
   endif
 
-  if (!isscalar (x) && !isscalar(lambda))
+  if (!isscalar (lambda))
     [retval, x, lambda] = common_size (x, lambda);
     if (retval > 0)
-      error ("exppdf: X and LAMBDA must be of common size or scalar");
+      error ("exppdf: X and LAMBDA must be of common size or scalars");
     endif
   endif
 
-  if (isscalar (x))
-    sz = size (lambda);
-  else
-    sz = size (x);
-  endif
-  pdf = zeros (sz);
-
-  k = find (!(lambda > 0) | isnan (x));
-  if (any (k))
-    pdf(k) = NaN;
+  if (iscomplex (x) || iscomplex (lambda))
+    error ("exppdf: X and LAMBDA must not be complex");
   endif
 
-  k = find ((x >= 0) & (x < Inf) & (lambda > 0));
-  if (any (k))
-    if isscalar (lambda)
-      pdf(k) = exp (- x(k) ./ lambda) ./ lambda;
-    elseif isscalar (x)
-      pdf(k) = exp (- x ./ lambda(k)) ./ lambda(k);
-    else
-      pdf(k) = exp (- x(k) ./ lambda(k)) ./ lambda(k);
-    endif
+  if (isa (x, "single") || isa (lambda, "single"))
+    pdf = zeros (size (x), "single");
+  else
+    pdf = zeros (size (x));
+  endif
+
+  k = isnan (x) | !(lambda > 0);
+  pdf(k) = NaN;
+
+  k = (x >= 0) & (x < Inf) & (lambda > 0);
+  if isscalar (lambda)
+    pdf(k) = exp (- x(k) / lambda) / lambda;
+  else
+    pdf(k) = exp (- x(k) ./ lambda(k)) ./ lambda(k);
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 0.5 1 Inf];
+%! y = gampdf (x, 1, 2);
+%!assert(exppdf (x, 2*ones(1,5)), y);
+%!assert(exppdf (x, 2*[1 0 NaN 1 1]), [y(1) NaN NaN y(4:5)]);
+%!assert(exppdf ([x, NaN], 2), [y, NaN]);
+
+%% Test class of input preserved
+%!assert(exppdf (single([x, NaN]), 2), single([y, NaN]));
+%!assert(exppdf ([x, NaN], single(2)), single([y, NaN]));
+
+%% Test input validation
+%!error exppdf ()
+%!error exppdf (1)
+%!error exppdf (1,2,3)
+%!error exppdf (ones(3),ones(2))
+%!error exppdf (ones(2),ones(3))
+%!error exppdf (i, 2)
+%!error exppdf (2, i)
+
--- a/scripts/statistics/distributions/exprnd.m
+++ b/scripts/statistics/distributions/exprnd.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,71 +18,100 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} exprnd (@var{lambda}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} exprnd (@var{lambda}, @var{sz})
-## Return an @var{r} by @var{c} matrix of random samples from the
-## exponential distribution with mean @var{lambda}, which must be a
-## scalar or of size @var{r} by @var{c}.  Or if @var{sz} is a vector,
-## create a matrix of size @var{sz}.
+## @deftypefn  {Function File} {} exprnd (@var{lambda})
+## @deftypefnx {Function File} {} exprnd (@var{lambda}, @var{r})
+## @deftypefnx {Function File} {} exprnd (@var{lambda}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} exprnd (@var{lambda}, [@var{sz}])
+## Return a matrix of random samples from the exponential distribution with
+## mean @var{lambda}.
 ##
-## If @var{r} and @var{c} are omitted, the size of the result matrix is
-## the size of @var{lambda}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the size of
+## @var{lambda}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the exponential distribution
 
-function rnd = exprnd (lambda, r, c)
-
-  if (nargin == 3)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("exprnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("exprnd: C must be a positive integer");
-    endif
-    sz = [r, c];
+function rnd = exprnd (lambda, varargin)
 
-    if (any (size (lambda) != 1)
-        && (length (size (lambda)) != length (sz) || any (size (lambda) != sz)))
-      error ("exprnd: LAMBDA must be scalar or of size [R, C]");
-    endif
-  elseif (nargin == 2)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
-    else
-      error ("exprnd: R must be a positive integer or vector");
-    endif
-
-    if (any (size (lambda) != 1)
-        && ((length (size (lambda)) != length (sz)) || any (size (lambda) != sz)))
-      error ("exprnd: LAMBDA must be scalar or of size SZ");
-    endif
-  elseif (nargin == 1)
-    sz = size (lambda);
-  else
+  if (nargin < 1)
     print_usage ();
   endif
 
+  if (nargin == 1)
+    sz = size (lambda);
+  elseif (nargin == 2)
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
+    else
+      error ("exprnd: dimension vector must be row vector of non-negative integers");
+    endif
+  elseif (nargin > 2)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("exprnd: dimensions must be non-negative integers");
+    endif
+    sz = [varargin{:}];
+  endif
+
+  if (!isscalar (lambda) && !isequal (size (lambda), sz))
+    error ("exprnd: LAMBDA must be scalar or of size SZ");
+  endif
+
+  if (iscomplex (lambda))
+    error ("exprnd: LAMBDA must not be complex");
+  endif
+
+  if (isa (lambda, "single"))
+    cls = "single";
+  else
+    cls = "double";
+  endif
 
   if (isscalar (lambda))
     if ((lambda > 0) && (lambda < Inf))
-      rnd = rande(sz) * lambda;
+      rnd = rande (sz) * lambda;
     else
-      rnd = NaN (sz);
+      rnd = NaN (sz, cls);
     endif
   else
-    rnd = zeros (sz);
-    k = find (!(lambda > 0) | !(lambda < Inf));
-    if (any (k))
-      rnd(k) = NaN;
-    endif
-    k = find ((lambda > 0) & (lambda < Inf));
-    if (any (k))
-      rnd(k) = rande(size(k)) .* lambda(k);
-    endif
+    rnd = NaN (sz, cls);
+
+    k = (lambda > 0) & (lambda < Inf);
+    rnd(k) = rande (sum (k(:)), 1) .* lambda(k)(:);
   endif
 
 endfunction
+
+
+%!assert(size (exprnd (2)), [1, 1]);
+%!assert(size (exprnd (ones(2,1))), [2, 1]);
+%!assert(size (exprnd (ones(2,2))), [2, 2]);
+%!assert(size (exprnd (1, 3)), [3, 3]);
+%!assert(size (exprnd (1, [4 1])), [4, 1]);
+%!assert(size (exprnd (1, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (exprnd (1)), "double");
+%!assert(class (exprnd (single(1))), "single");
+%!assert(class (exprnd (single([1 1]))), "single");
+
+%% Test input validation
+%!error exprnd ()
+%!error exprnd (1, -1)
+%!error exprnd (1, ones(2))
+%!error exprnd (i)
+%!error exprnd (1, [2 -1 2])
+%!error exprnd (1, 2, -1)
+%!error exprnd (1, 2, ones(2))
+%!error exprnd (ones(2,2), 3)
+%!error exprnd (ones(2,2), [3, 2])
+%!error exprnd (ones(2,2), 2, 3)
+
--- a/scripts/statistics/distributions/fcdf.m
+++ b/scripts/statistics/distributions/fcdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,9 +19,9 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} fcdf (@var{x}, @var{m}, @var{n})
-## For each element of @var{x}, compute the CDF at @var{x} of the F
-## distribution with @var{m} and @var{n} degrees of freedom, i.e.,
-## PROB (F (@var{m}, @var{n}) @leq{} @var{x}).
+## For each element of @var{x}, compute the cumulative distribution function
+## (CDF) at @var{x} of the F distribution with @var{m} and @var{n} degrees of
+## freedom.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -35,31 +36,61 @@
   if (!isscalar (m) || !isscalar (n))
     [retval, x, m, n] = common_size (x, m, n);
     if (retval > 0)
-      error ("fcdf: X, M and N must be of common size or scalar");
+      error ("fcdf: X, M, and N must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  cdf = zeros (sz);
+  if (iscomplex (x) || iscomplex (m) || iscomplex (n))
+    error ("fcdf: X, M, and N must not be complex");
+  endif
 
-  k = find (!(m > 0) | !(n > 0) | isnan (x));
-  if (any (k))
-    cdf(k) = NaN;
+  if (isa (x, "single") || isa (m, "single") || isa (n, "single"))
+    cdf = zeros (size (x), "single");
+  else
+    cdf = zeros (size (x));
   endif
 
-  k = find ((x == Inf) & (m > 0) & (n > 0));
-  if (any (k))
-    cdf(k) = 1;
-  endif
+  k = isnan (x) | !(m > 0) | !(m < Inf) | !(n > 0) | !(n < Inf);
+  cdf(k) = NaN;
+
+  k = (x == Inf) & (m > 0) & (m < Inf) & (n > 0) & (n < Inf);
+  cdf(k) = 1;
 
-  k = find ((x > 0) & (x < Inf) & (m > 0) & (n > 0));
-  if (any (k))
-    if (isscalar (m) && isscalar (n))
-      cdf(k) = 1 - betainc (1 ./ (1 + m .* x(k) ./ n), n / 2, m / 2);
-    else
-      cdf(k) = 1 - betainc (1 ./ (1 + m(k) .* x(k) ./ n(k)), n(k) / 2,
-                            m(k) / 2);
-    endif
+  k = (x > 0) & (x < Inf) & (m > 0) & (m < Inf) & (n > 0) & (n < Inf);
+  if (isscalar (m) && isscalar (n))
+    cdf(k) = 1 - betainc (1 ./ (1 + m * x(k) / n), n/2, m/2);
+  else
+    cdf(k) = 1 - betainc (1 ./ (1 + m(k) .* x(k) ./ n(k)), n(k)/2, m(k)/2);
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 0.5 1 2 Inf];
+%! y = [0 0 1/3 1/2 2/3 1];
+%!assert(fcdf (x, 2*ones(1,6), 2*ones(1,6)), y, eps);
+%!assert(fcdf (x, 2, 2*ones(1,6)), y, eps);
+%!assert(fcdf (x, 2*ones(1,6), 2), y, eps);
+%!assert(fcdf (x, [0 NaN Inf 2 2 2], 2), [NaN NaN NaN y(4:6)], eps);
+%!assert(fcdf (x, 2, [0 NaN Inf 2 2 2]), [NaN NaN NaN y(4:6)], eps);
+%!assert(fcdf ([x(1:2) NaN x(4:6)], 2, 2), [y(1:2) NaN y(4:6)], eps);
+
+%% Test class of input preserved
+%!assert(fcdf ([x, NaN], 2, 2), [y, NaN], eps);
+%!assert(fcdf (single([x, NaN]), 2, 2), single([y, NaN]), eps("single"));
+%!assert(fcdf ([x, NaN], single(2), 2), single([y, NaN]), eps("single"));
+%!assert(fcdf ([x, NaN], 2, single(2)), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error fcdf ()
+%!error fcdf (1)
+%!error fcdf (1,2)
+%!error fcdf (1,2,3,4)
+%!error fcdf (ones(3),ones(2),ones(2))
+%!error fcdf (ones(2),ones(3),ones(2))
+%!error fcdf (ones(2),ones(2),ones(3))
+%!error fcdf (i, 2, 2)
+%!error fcdf (2, i, 2)
+%!error fcdf (2, 2, i)
+
--- a/scripts/statistics/distributions/finv.m
+++ b/scripts/statistics/distributions/finv.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,9 +19,9 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} finv (@var{x}, @var{m}, @var{n})
-## For each component of @var{x}, compute the quantile (the inverse of
-## the CDF) at @var{x} of the F distribution with parameters @var{m} and
-## @var{n}.
+## For each element of @var{x}, compute the quantile (the inverse of
+## the CDF) at @var{x} of the F distribution with @var{m} and @var{n}
+## degrees of freedom.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -35,31 +36,58 @@
   if (!isscalar (m) || !isscalar (n))
     [retval, x, m, n] = common_size (x, m, n);
     if (retval > 0)
-      error ("finv: X, M and N must be of common size or scalar");
+      error ("finv: X, M, and N must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  inv = zeros (sz);
+  if (iscomplex (x) || iscomplex (m) || iscomplex (n))
+    error ("finv: X, M, and N must not be complex");
+  endif
 
-  k = find ((x < 0) | (x > 1) | isnan (x) | !(m > 0) | !(n > 0));
-  if (any (k))
-    inv(k) = NaN;
+  if (isa (x, "single") || isa (m, "single") || isa (n, "single"))
+    inv = NaN (size (x), "single");
+  else
+    inv = NaN (size (x));
   endif
 
-  k = find ((x == 1) & (m > 0) & (n > 0));
-  if (any (k))
-    inv(k) = Inf;
-  endif
+  k = (x == 1) & (m > 0) & (m < Inf) & (n > 0) & (n < Inf);
+  inv(k) = Inf;
 
-  k = find ((x > 0) & (x < 1) & (m > 0) & (n > 0));
-  if (any (k))
-    if (isscalar (m) && isscalar (n))
-      inv(k) = ((1 ./ betainv (1 - x(k), n / 2, m / 2) - 1) .* n ./ m);
-    else
-      inv(k) = ((1 ./ betainv (1 - x(k), n(k) / 2, m(k) / 2) - 1)
-                .* n(k) ./ m(k));
-    endif
+  k = (x >= 0) & (x < 1) & (m > 0) & (m < Inf) & (n > 0) & (n < Inf);
+  if (isscalar (m) && isscalar (n))
+    inv(k) = ((1 ./ betainv (1 - x(k), n/2, m/2) - 1) * n / m);
+  else
+    inv(k) = ((1 ./ betainv (1 - x(k), n(k)/2, m(k)/2) - 1)
+              .* n(k) ./ m(k));
   endif
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.5 1 2];
+%!assert(finv (x, 2*ones(1,5), 2*ones(1,5)), [NaN 0 1 Inf NaN]);
+%!assert(finv (x, 2, 2*ones(1,5)), [NaN 0 1 Inf NaN]);
+%!assert(finv (x, 2*ones(1,5), 2), [NaN 0 1 Inf NaN]);
+%!assert(finv (x, [2 -Inf NaN Inf 2], 2), [NaN NaN NaN NaN NaN]);
+%!assert(finv (x, 2, [2 -Inf NaN Inf 2]), [NaN NaN NaN NaN NaN]);
+%!assert(finv ([x(1:2) NaN x(4:5)], 2, 2), [NaN 0 NaN Inf NaN]);
+
+%% Test class of input preserved
+%!assert(finv ([x, NaN], 2, 2), [NaN 0 1 Inf NaN NaN]);
+%!assert(finv (single([x, NaN]), 2, 2), single([NaN 0 1 Inf NaN NaN]));
+%!assert(finv ([x, NaN], single(2), 2), single([NaN 0 1 Inf NaN NaN]));
+%!assert(finv ([x, NaN], 2, single(2)), single([NaN 0 1 Inf NaN NaN]));
+
+%% Test input validation
+%!error finv ()
+%!error finv (1)
+%!error finv (1,2)
+%!error finv (1,2,3,4)
+%!error finv (ones(3),ones(2),ones(2))
+%!error finv (ones(2),ones(3),ones(2))
+%!error finv (ones(2),ones(2),ones(3))
+%!error finv (i, 2, 2)
+%!error finv (2, i, 2)
+%!error finv (2, 2, i)
+
--- a/scripts/statistics/distributions/fpdf.m
+++ b/scripts/statistics/distributions/fpdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -35,31 +36,70 @@
   if (!isscalar (m) || !isscalar (n))
     [retval, x, m, n] = common_size (x, m, n);
     if (retval > 0)
-      error ("fpdf: X, M and N must be of common size or scalar");
+      error ("fpdf: X, M, and N must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  pdf = zeros (sz);
+  if (iscomplex (x) || iscomplex (m) || iscomplex (n))
+    error ("fpdf: X, M, and N must not be complex");
+  endif
 
-  k = find (isnan (x) | !(m > 0) | !(n > 0));
-  if (any (k))
-    pdf(k) = NaN;
+  if (isa (x, "single") || isa (m, "single") || isa (n, "single"))
+    pdf = zeros (size (x), "single");
+  else
+    pdf = zeros (size (x));
   endif
 
-  k = find ((x > 0) & (x < Inf) & (m > 0) & (n > 0));
-  if (any (k))
-    if (isscalar (m) && isscalar (n))
-      tmp = m / n * x(k);
-      pdf(k) = (exp ((m / 2 - 1) .* log (tmp)
-                     - ((m + n) / 2) .* log (1 + tmp))
-                .* (m / n) ./ beta (m / 2, n / 2));
-    else
-      tmp = m(k) .* x(k) ./ n(k);
-      pdf(k) = (exp ((m(k) / 2 - 1) .* log (tmp)
-                     - ((m(k) + n(k)) / 2) .* log (1 + tmp))
-                .* (m(k) ./ n(k)) ./ beta (m(k) / 2, n(k) / 2));
-    endif
+  k = isnan (x) | !(m > 0) | !(m < Inf) | !(n > 0) | !(n < Inf);
+  pdf(k) = NaN;
+
+  k = (x > 0) & (x < Inf) & (m > 0) & (m < Inf) & (n > 0) & (n < Inf);
+  if (isscalar (m) && isscalar (n))
+    tmp = m / n * x(k);
+    pdf(k) = (exp ((m/2 - 1) * log (tmp)
+                   - ((m + n) / 2) * log (1 + tmp))
+              * (m / n) ./ beta (m/2, n/2));
+  else
+    tmp = m(k) .* x(k) ./ n(k);
+    pdf(k) = (exp ((m(k)/2 - 1) .* log (tmp)
+                   - ((m(k) + n(k)) / 2) .* log (1 + tmp))
+              .* (m(k) ./ n(k)) ./ beta (m(k)/2, n(k)/2));
   endif
 
 endfunction
+
+
+%% F (x, 1, m) == T distribution (sqrt (x), m) / sqrt (x)
+%!test
+%! x = rand (10,1);
+%! x = x(x > 0.1 & x < 0.9);
+%! y = tpdf (sqrt (x), 2) ./ sqrt (x);
+%! assert(fpdf (x, 1, 2), y, 5*eps);
+
+%!shared x,y
+%! x = [-1 0 0.5 1 2];
+%! y = [0 0 4/9 1/4 1/9];
+%!assert(fpdf (x, 2*ones(1,5), 2*ones(1,5)), y, eps);
+%!assert(fpdf (x, 2, 2*ones(1,5)), y, eps);
+%!assert(fpdf (x, 2*ones(1,5), 2), y, eps);
+%!assert(fpdf (x, [0 NaN Inf 2 2], 2), [NaN NaN NaN y(4:5)], eps);
+%!assert(fpdf (x, 2, [0 NaN Inf 2 2]), [NaN NaN NaN y(4:5)], eps);
+%!assert(fpdf ([x, NaN], 2, 2), [y, NaN], eps);
+
+%% Test class of input preserved
+%!assert(fpdf (single([x, NaN]), 2, 2), single([y, NaN]), eps("single"));
+%!assert(fpdf ([x, NaN], single(2), 2), single([y, NaN]), eps("single"));
+%!assert(fpdf ([x, NaN], 2, single(2)), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error fpdf ()
+%!error fpdf (1)
+%!error fpdf (1,2)
+%!error fpdf (1,2,3,4)
+%!error fpdf (ones(3),ones(2),ones(2))
+%!error fpdf (ones(2),ones(3),ones(2))
+%!error fpdf (ones(2),ones(2),ones(3))
+%!error fpdf (i, 2, 2)
+%!error fpdf (2, i, 2)
+%!error fpdf (2, 2, i)
+
--- a/scripts/statistics/distributions/frnd.m
+++ b/scripts/statistics/distributions/frnd.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,103 +18,115 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} frnd (@var{m}, @var{n}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} frnd (@var{m}, @var{n}, @var{sz})
-## Return an @var{r} by @var{c} matrix of random samples from the F
-## distribution with @var{m} and @var{n} degrees of freedom.  Both
-## @var{m} and @var{n} must be scalar or of size @var{r} by @var{c}.
-## If @var{sz} is a vector the random samples are in a matrix of
-## size @var{sz}.
+## @deftypefn  {Function File} {} frnd (@var{m}, @var{n})
+## @deftypefnx {Function File} {} frnd (@var{m}, @var{n}, @var{r})
+## @deftypefnx {Function File} {} frnd (@var{m}, @var{n}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} frnd (@var{m}, @var{n}, [@var{sz}])
+## Return a matrix of random samples from the F distribution with
+## @var{m} and @var{n} degrees of freedom.
 ##
-## If @var{r} and @var{c} are omitted, the size of the result matrix is
-## the common size of @var{m} and @var{n}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the common size of
+## @var{m} and @var{n}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the F distribution
 
-function rnd = frnd (m, n, r, c)
+function rnd = frnd (m, n, varargin)
 
-  if (nargin > 1)
-    if (!isscalar(m) || !isscalar(n))
-      [retval, m, n] = common_size (m, n);
-      if (retval > 0)
-        error ("frnd: M and N must be of common size or scalar");
-      endif
+  if (nargin < 2)
+    print_usage ();
+  endif
+
+  if (!isscalar (m) || !isscalar (n))
+    [retval, m, n] = common_size (m, n);
+    if (retval > 0)
+      error ("frnd: M and N must be of common size or scalars");
     endif
   endif
 
-
-  if (nargin == 4)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("frnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("frnd: C must be a positive integer");
-    endif
-    sz = [r, c];
-
-    if (any (size (m) != 1)
-        && ((length (size (m)) != length (sz)) || any (size (m) != sz)))
-      error ("frnd: M and N must be scalar or of size [R,C]");
-    endif
-  elseif (nargin == 3)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
-    else
-      error ("frnd: R must be a positive integer or vector");
-    endif
-
-    if (any (size (m) != 1)
-        && ((length (size (m)) != length (sz)) || any (size (m) != sz)))
-      error ("frnd: M and N must be scalar or of size SZ");
-    endif
-  elseif (nargin == 2)
-    sz = size(m);
-  else
-    print_usage ();
+  if (iscomplex (m) || iscomplex (n))
+    error ("frnd: M and N must not be complex");
   endif
 
+  if (nargin == 2)
+    sz = size (m);
+  elseif (nargin == 3)
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
+    else
+      error ("frnd: dimension vector must be row vector of non-negative integers");
+    endif
+  elseif (nargin > 3)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("frnd: dimensions must be non-negative integers");
+    endif
+    sz = [varargin{:}];
+  endif
+
+  if (!isscalar (m) && !isequal (size (m), sz))
+    error ("frnd: M and N must be scalar or of size SZ");
+  endif
+
+  if (isa (m, "single") || isa (n, "single"))
+    cls = "single";
+  else
+    cls = "double";
+  endif
 
   if (isscalar (m) && isscalar (n))
-    if (isinf (m) || isinf (n))
-      if (isinf (m))
-        rnd = ones (sz);
-      else
-        rnd = 2 ./ m .* randg(m / 2, sz);
-      endif
-      if (! isinf (n))
-        rnd = 0.5 .* n .* rnd ./ randg (n / 2, sz);
-      endif
-    elseif ((m > 0) && (m < Inf) && (n > 0) && (n < Inf))
-      rnd = n ./ m .* randg (m / 2, sz) ./ randg (n / 2, sz);
+    if ((m > 0) && (m < Inf) && (n > 0) && (n < Inf))
+      rnd = n/m * randg (m/2, sz) ./ randg (n/2, sz);
     else
-      rnd = NaN (sz);
+      rnd = NaN (sz, cls);
     endif
   else
-    rnd = zeros (sz);
-
-    k = find (isinf(m) | isinf(n));
-    if (any (k))
-      rnd (k) = 1;
-      k2 = find (!isinf(m) & isinf(n));
-      rnd (k2) = 2 ./ m(k2) .* randg (m(k2) ./ 2, size(k2));
-      k2 = find (isinf(m) & !isinf(n));
-      rnd (k2) = 0.5 .* n(k2) .* rnd(k2) ./ randg (n(k2) ./ 2, size(k2));
-    endif
+    rnd = NaN (sz, cls);
 
-    k = find (!(m > 0) | !(n > 0));
-    if (any (k))
-      rnd(k) = NaN;
-    endif
-
-    k = find ((m > 0) & (m < Inf) &
-              (n > 0) & (n < Inf));
-    if (any (k))
-      rnd(k) = n(k) ./ m(k) .* randg(m(k)./2,size(k)) ./ randg(n(k)./2,size(k));
-    endif
+    k = (m > 0) & (m < Inf) & (n > 0) & (n < Inf);
+    rnd(k) = n(k) ./ m(k) .* randg (m(k)/2) ./ randg (n(k)/2);
   endif
 
 endfunction
+
+
+%!assert(size (frnd (1,2)), [1, 1]);
+%!assert(size (frnd (ones(2,1), 2)), [2, 1]);
+%!assert(size (frnd (ones(2,2), 2)), [2, 2]);
+%!assert(size (frnd (1, 2*ones(2,1))), [2, 1]);
+%!assert(size (frnd (1, 2*ones(2,2))), [2, 2]);
+%!assert(size (frnd (1, 2, 3)), [3, 3]);
+%!assert(size (frnd (1, 2, [4 1])), [4, 1]);
+%!assert(size (frnd (1, 2, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (frnd (1, 2)), "double");
+%!assert(class (frnd (single(1), 2)), "single");
+%!assert(class (frnd (single([1 1]), 2)), "single");
+%!assert(class (frnd (1, single(2))), "single");
+%!assert(class (frnd (1, single([2 2]))), "single");
+
+%% Test input validation
+%!error frnd ()
+%!error frnd (1)
+%!error frnd (ones(3),ones(2))
+%!error frnd (ones(2),ones(3))
+%!error frnd (i, 2)
+%!error frnd (2, i)
+%!error frnd (1,2, -1)
+%!error frnd (1,2, ones(2))
+%!error frnd (1, 2, [2 -1 2])
+%!error frnd (1,2, 1, ones(2))
+%!error frnd (1,2, 1, -1)
+%!error frnd (ones(2,2), 2, 3)
+%!error frnd (ones(2,2), 2, [3, 2])
+%!error frnd (ones(2,2), 2, 2, 3)
+
--- a/scripts/statistics/distributions/gamcdf.m
+++ b/scripts/statistics/distributions/gamcdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -21,7 +22,6 @@
 ## For each element of @var{x}, compute the cumulative distribution
 ## function (CDF) at @var{x} of the Gamma distribution with parameters
 ## @var{a} and @var{b}.
-## @seealso{gamma, gammaln, gammainc, gampdf, gaminv, gamrnd}
 ## @end deftypefn
 
 ## Author: TT <Teresa.Twaroch@ci.tuwien.ac.at>
@@ -33,28 +33,59 @@
     print_usage ();
   endif
 
-  if (!isscalar (a) || !isscalar(b))
+  if (!isscalar (a) || !isscalar (b))
     [retval, x, a, b] = common_size (x, a, b);
     if (retval > 0)
-      error ("gamcdf: X, A and B must be of common size or scalars");
+      error ("gamcdf: X, A, and B must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  cdf = zeros (sz);
-
-  k = find (!(a > 0) | !(b > 0) | isnan (x));
-  if (any (k))
-    cdf (k) = NaN;
+  if (iscomplex (x) || iscomplex (a) || iscomplex (b))
+    error ("gamcdf: X, A, and B must not be complex");
   endif
 
-  k = find ((x > 0) & (a > 0) & (b > 0));
-  if (any (k))
-    if (isscalar (a) && isscalar(b))
-      cdf (k) = gammainc (x(k) ./ b, a);
-    else
-      cdf (k) = gammainc (x(k) ./ b(k), a(k));
-    endif
+  if (isa (x, "single") || isa (a, "single") || isa (b, "single"))
+    cdf = zeros (size (x), "single");
+  else
+    cdf = zeros (size (x));
+  endif
+
+  k = isnan (x) | !(a > 0) | !(a < Inf) | !(b > 0) | !(b < Inf);
+  cdf(k) = NaN;
+
+  k = (x > 0) & (a > 0) & (a < Inf) & (b > 0) & (b < Inf);
+  if (isscalar (a) && isscalar (b))
+    cdf(k) = gammainc (x(k) / b, a);
+  else
+    cdf(k) = gammainc (x(k) ./ b(k), a(k));
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 0.5 1 2 Inf];
+%! y = [0, gammainc(x(2:end), 1)];
+%!assert(gamcdf (x, ones(1,6), ones(1,6)), y);
+%!assert(gamcdf (x, 1, ones(1,6)), y);
+%!assert(gamcdf (x, ones(1,6), 1), y);
+%!assert(gamcdf (x, [0 -Inf NaN Inf 1 1], 1), [NaN NaN NaN NaN y(5:6)]);
+%!assert(gamcdf (x, 1, [0 -Inf NaN Inf 1 1]), [NaN NaN NaN NaN y(5:6)]);
+%!assert(gamcdf ([x(1:2) NaN x(4:6)], 1, 1), [y(1:2) NaN y(4:6)]);
+
+%% Test class of input preserved
+%!assert(gamcdf ([x, NaN], 1, 1), [y, NaN]);
+%!assert(gamcdf (single([x, NaN]), 1, 1), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error gamcdf ()
+%!error gamcdf (1)
+%!error gamcdf (1,2)
+%!error gamcdf (1,2,3,4)
+%!error gamcdf (ones(3),ones(2),ones(2))
+%!error gamcdf (ones(2),ones(3),ones(2))
+%!error gamcdf (ones(2),ones(2),ones(3))
+%!error gamcdf (i, 2, 2)
+%!error gamcdf (2, i, 2)
+%!error gamcdf (2, 2, i)
+
--- a/scripts/statistics/distributions/gaminv.m
+++ b/scripts/statistics/distributions/gaminv.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,10 +19,9 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} gaminv (@var{x}, @var{a}, @var{b})
-## For each component of @var{x}, compute the quantile (the inverse of
+## For each element of @var{x}, compute the quantile (the inverse of
 ## the CDF) at @var{x} of the Gamma distribution with parameters @var{a}
 ## and @var{b}.
-## @seealso{gamma, gammaln, gammainc, gampdf, gamcdf, gamrnd}
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -33,36 +33,40 @@
     print_usage ();
   endif
 
-  if (!isscalar (a) || !isscalar(b))
+  if (!isscalar (a) || !isscalar (b))
     [retval, x, a, b] = common_size (x, a, b);
     if (retval > 0)
-      error ("gaminv: X, A and B must be of common size or scalars");
+      error ("gaminv: X, A, and B must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  inv = zeros (sz);
+  if (iscomplex (x) || iscomplex (a) || iscomplex (b))
+    error ("gaminv: X, A, and B must not be complex");
+  endif
 
-  k = find ((x < 0) | (x > 1) | isnan (x) | !(a > 0) | !(b > 0));
-  if (any (k))
-    inv (k) = NaN;
+  if (isa (x, "single") || isa (a, "single") || isa (b, "single"))
+    inv = zeros (size (x), "single");
+  else
+    inv = zeros (size (x));
   endif
 
-  k = find ((x == 1) & (a > 0) & (b > 0));
-  if (any (k))
-    inv (k) = Inf;
-  endif
+  k = ((x < 0) | (x > 1) | isnan (x)
+       | !(a > 0) | !(a < Inf) | !(b > 0) | !(b < Inf));
+  inv(k) = NaN;
 
-  k = find ((x > 0) & (x < 1) & (a > 0) & (b > 0));
+  k = (x == 1) & (a > 0) & (a < Inf) & (b > 0) & (b < Inf);
+  inv(k) = Inf;
+
+  k = find ((x > 0) & (x < 1) & (a > 0) & (a < Inf) & (b > 0) & (b < Inf));
   if (any (k))
-    if (!isscalar(a) || !isscalar(b))
-      a = a (k);
-      b = b (k);
+    if (!isscalar (a) || !isscalar (b))
+      a = a(k);
+      b = b(k);
       y = a .* b;
     else
       y = a * b * ones (size (k));
     endif
-    x = x (k);
+    x = x(k);
 
     if (isa (x, "single"))
       myeps = eps ("single");
@@ -90,7 +94,36 @@
       y_old = y_new;
     endfor
 
-    inv (k) = y_new;
+    inv(k) = y_new;
   endif
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.63212055882855778 1 2];
+%!assert(gaminv (x, ones(1,5), ones(1,5)), [NaN 0 1 Inf NaN], eps);
+%!assert(gaminv (x, 1, ones(1,5)), [NaN 0 1 Inf NaN], eps);
+%!assert(gaminv (x, ones(1,5), 1), [NaN 0 1 Inf NaN], eps);
+%!assert(gaminv (x, [1 -Inf NaN Inf 1], 1), [NaN NaN NaN NaN NaN]);
+%!assert(gaminv (x, 1, [1 -Inf NaN Inf 1]), [NaN NaN NaN NaN NaN]);
+%!assert(gaminv ([x(1:2) NaN x(4:5)], 1, 1), [NaN 0 NaN Inf NaN]);
+
+%% Test class of input preserved
+%!assert(gaminv ([x, NaN], 1, 1), [NaN 0 1 Inf NaN NaN], eps);
+%!assert(gaminv (single([x, NaN]), 1, 1), single([NaN 0 1 Inf NaN NaN]), eps("single"));
+%!assert(gaminv ([x, NaN], single(1), 1), single([NaN 0 1 Inf NaN NaN]), eps("single"));
+%!assert(gaminv ([x, NaN], 1, single(1)), single([NaN 0 1 Inf NaN NaN]), eps("single"));
+
+%% Test input validation
+%!error gaminv ()
+%!error gaminv (1)
+%!error gaminv (1,2)
+%!error gaminv (1,2,3,4)
+%!error gaminv (ones(3),ones(2),ones(2))
+%!error gaminv (ones(2),ones(3),ones(2))
+%!error gaminv (ones(2),ones(2),ones(3))
+%!error gaminv (i, 2, 2)
+%!error gaminv (2, i, 2)
+%!error gaminv (2, 2, i)
+
--- a/scripts/statistics/distributions/gampdf.m
+++ b/scripts/statistics/distributions/gampdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -21,7 +22,6 @@
 ## For each element of @var{x}, return the probability density function
 ## (PDF) at @var{x} of the Gamma distribution with parameters @var{a}
 ## and @var{b}.
-## @seealso{gamma, gammaln, gammainc, gamcdf, gaminv, gamrnd}
 ## @end deftypefn
 
 ## Author: TT <Teresa.Twaroch@ci.tuwien.ac.at>
@@ -33,41 +33,71 @@
     print_usage ();
   endif
 
-  if (!isscalar (a) || !isscalar(b))
+  if (!isscalar (a) || !isscalar (b))
     [retval, x, a, b] = common_size (x, a, b);
     if (retval > 0)
-      error ("gampdf: X, A and B must be of common size or scalars");
+      error ("gampdf: X, A, and B must be of common size or scalars");
     endif
   endif
 
-  sz = size(x);
-  pdf = zeros (sz);
+  if (iscomplex (x) || iscomplex (a) || iscomplex (b))
+    error ("gampdf: X, A, and B must not be complex");
+  endif
 
-  k = find (!(a > 0) | !(b > 0) | isnan (x));
-  if (any (k))
-    pdf (k) = NaN;
+  if (isa (x, "single") || isa (a, "single") || isa (b, "single"))
+    pdf = zeros (size (x), "single");
+  else
+    pdf = zeros (size (x));
   endif
 
-  k = find ((x >= 0) & (a > 0) & (a <= 1) & (b > 0));
-  if (any (k))
-    if (isscalar(a) && isscalar(b))
-      pdf(k) = (x(k) .^ (a - 1)) ...
-                .* exp(- x(k) ./ b) ./ gamma (a) ./ (b .^ a);
-    else
-      pdf(k) = (x(k) .^ (a(k) - 1)) ...
-                .* exp(- x(k) ./ b(k)) ./ gamma (a(k)) ./ (b(k) .^ a(k));
-    endif
+  k = !(a > 0) | !(b > 0) | isnan (x);
+  pdf(k) = NaN;
+
+  k = (x >= 0) & (a > 0) & (a <= 1) & (b > 0);
+  if (isscalar (a) && isscalar (b))
+    pdf(k) = (x(k) .^ (a - 1)) ...
+              .* exp (- x(k) / b) / gamma (a) / (b ^ a);
+  else
+    pdf(k) = (x(k) .^ (a(k) - 1)) ...
+              .* exp (- x(k) ./ b(k)) ./ gamma (a(k)) ./ (b(k) .^ a(k));
   endif
 
-  k = find ((x >= 0) & (a > 1) & (b > 0));
-  if (any (k))
-    if (isscalar(a) && isscalar(b))
-      pdf(k) = exp (- a .* log (b) + (a-1) .* log (x(k))
-                    - x(k) ./ b - gammaln (a));
-    else
-      pdf(k) = exp (- a(k) .* log (b(k)) + (a(k)-1) .* log (x(k))
-                    - x(k) ./ b(k) - gammaln (a(k)));
-    endif
+  k = (x >= 0) & (a > 1) & (b > 0);
+  if (isscalar (a) && isscalar (b))
+    pdf(k) = exp (- a * log (b) + (a-1) * log (x(k))
+                  - x(k) / b - gammaln (a));
+  else
+    pdf(k) = exp (- a(k) .* log (b(k)) + (a(k)-1) .* log (x(k))
+                  - x(k) ./ b(k) - gammaln (a(k)));
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 0.5 1 Inf];
+%! y = [0 exp(-x(2:end))];
+%!assert(gampdf (x, ones(1,5), ones(1,5)), y);
+%!assert(gampdf (x, 1, ones(1,5)), y);
+%!assert(gampdf (x, ones(1,5), 1), y);
+%!assert(gampdf (x, [0 -Inf NaN Inf 1], 1), [NaN NaN NaN NaN y(5)]);
+%!assert(gampdf (x, 1, [0 -Inf NaN Inf 1]), [NaN NaN NaN 0 y(5)]);
+%!assert(gampdf ([x, NaN], 1, 1), [y, NaN]);
+
+%% Test class of input preserved
+%!assert(gampdf (single([x, NaN]), 1, 1), single([y, NaN]));
+%!assert(gampdf ([x, NaN], single(1), 1), single([y, NaN]));
+%!assert(gampdf ([x, NaN], 1, single(1)), single([y, NaN]));
+
+%% Test input validation
+%!error gampdf ()
+%!error gampdf (1)
+%!error gampdf (1,2)
+%!error gampdf (1,2,3,4)
+%!error gampdf (ones(3),ones(2),ones(2))
+%!error gampdf (ones(2),ones(3),ones(2))
+%!error gampdf (ones(2),ones(2),ones(3))
+%!error gampdf (i, 2, 2)
+%!error gampdf (2, i, 2)
+%!error gampdf (2, 2, i)
+
--- a/scripts/statistics/distributions/gamrnd.m
+++ b/scripts/statistics/distributions/gamrnd.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,81 +18,118 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} gamrnd (@var{a}, @var{b}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} gamrnd (@var{a}, @var{b}, @var{sz})
-## Return an @var{r} by @var{c} or a @code{size (@var{sz})} matrix of
-## random samples from the Gamma distribution with parameters @var{a}
-## and @var{b}.  Both @var{a} and @var{b} must be scalar or of size
-## @var{r} by @var{c}.
+## @deftypefn  {Function File} {} gamrnd (@var{a}, @var{b})
+## @deftypefnx {Function File} {} gamrnd (@var{a}, @var{b}, @var{r})
+## @deftypefnx {Function File} {} gamrnd (@var{a}, @var{b}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} gamrnd (@var{a}, @var{b}, [@var{sz}])
+## Return a matrix of random samples from the Gamma distribution with
+## parameters @var{a} and @var{b}.
 ##
-## If @var{r} and @var{c} are omitted, the size of the result matrix is
-## the common size of @var{a} and @var{b}.
-## @seealso{gamma, gammaln, gammainc, gampdf, gamcdf, gaminv}
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the common size of
+## @var{a} and @var{b}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the Gamma distribution
 
-function rnd = gamrnd (a, b, r, c)
+function rnd = gamrnd (a, b, varargin)
 
-  if (nargin > 1)
-    if (!isscalar(a) || !isscalar(b))
-      [retval, a, b] = common_size (a, b);
-      if (retval > 0)
-        error ("gamrnd: A and B must be of common size or scalar");
-      endif
+  if (nargin < 2)
+    print_usage ();
+  endif
+
+  if (!isscalar (a) || !isscalar (b))
+    [retval, a, b] = common_size (a, b);
+    if (retval > 0)
+      error ("gamrnd: A and B must be of common size or scalars");
     endif
   endif
 
-  if (nargin == 4)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("gamrnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("gamrnd: C must be a positive integer");
-    endif
-    sz = [r, c];
+  if (iscomplex (a) || iscomplex (b))
+    error ("gamrnd: A and B must not be complex");
+  endif
 
-    if (any (size (a) != 1)
-        && (length (size (a)) != length (sz) || any (size (a) != sz)))
-      error ("gamrnd: A and B must be scalar or of size [R, C]");
-    endif
+  if (nargin == 2)
+    sz = size (a);
   elseif (nargin == 3)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
     else
-      error ("gamrnd: R must be a positive integer or vector");
+      error ("gamrnd: dimension vector must be row vector of non-negative integers");
     endif
-
-    if (any (size (a) != 1)
-        && (length (size (a)) != length (sz) || any (size (a) != sz)))
-      error ("gamrnd: A and B must be scalar or of size SZ");
+  elseif (nargin > 3)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("gamrnd: dimensions must be non-negative integers");
     endif
-  elseif (nargin == 2)
-    sz = size(a);
-  else
-    print_usage ();
+    sz = [varargin{:}];
   endif
 
-  rnd = zeros (sz);
+  if (!isscalar (a) && !isequal (size (a), sz))
+    error ("gamrnd: A and B must be scalar or of size SZ");
+  endif
 
-  if (isscalar (a) && isscalar(b))
-    if (find (!(a > 0) | !(a < Inf) | !(b > 0) | !(b < Inf)))
-      rnd = NaN (sz);
-    else
-      rnd = b .* randg(a, sz);
+  if (isa (a, "single") || isa (b, "single"))
+    cls = "single";
+  else
+    cls = "double";
+  endif
+
+  if (isscalar (a) && isscalar (b))
+    if ((a > 0) && (a < Inf) && (b > 0) && (b < Inf))
+      rnd = b * randg (a, sz);
+      if (strcmp (cls, "single"))
+        rnd = single (rnd);
+      endif
+    else 
+      rnd = NaN (sz, cls);
     endif
   else
-    k = find (!(a > 0) | !(a < Inf) | !(b > 0) | !(b < Inf));
-    if (any (k))
-      rnd(k) = NaN;
-    endif
-    k = find ((a > 0) & (a < Inf) & (b > 0) & (b < Inf));
-    if (any (k))
-      rnd(k) = b(k) .* randg(a(k), size(k));
-    endif
+    rnd = NaN (sz, cls);
+
+    k = (a > 0) & (a < Inf) & (b > 0) & (b < Inf);
+    rnd(k) = b(k) .* randg (a(k));
   endif
 
 endfunction
+
+
+%!assert(size (gamrnd (1,2)), [1, 1]);
+%!assert(size (gamrnd (ones(2,1), 2)), [2, 1]);
+%!assert(size (gamrnd (ones(2,2), 2)), [2, 2]);
+%!assert(size (gamrnd (1, 2*ones(2,1))), [2, 1]);
+%!assert(size (gamrnd (1, 2*ones(2,2))), [2, 2]);
+%!assert(size (gamrnd (1, 2, 3)), [3, 3]);
+%!assert(size (gamrnd (1, 2, [4 1])), [4, 1]);
+%!assert(size (gamrnd (1, 2, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (gamrnd (1, 2)), "double");
+%!assert(class (gamrnd (single(1), 2)), "single");
+%!assert(class (gamrnd (single([1 1]), 2)), "single");
+%!assert(class (gamrnd (1, single(2))), "single");
+%!assert(class (gamrnd (1, single([2 2]))), "single");
+
+%% Test input validation
+%!error gamrnd ()
+%!error gamrnd (1)
+%!error gamrnd (ones(3),ones(2))
+%!error gamrnd (ones(2),ones(3))
+%!error gamrnd (i, 2)
+%!error gamrnd (2, i)
+%!error gamrnd (1,2, -1)
+%!error gamrnd (1,2, ones(2))
+%!error gamrnd (1, 2, [2 -1 2])
+%!error gamrnd (1,2, 1, ones(2))
+%!error gamrnd (1,2, 1, -1)
+%!error gamrnd (ones(2,2), 2, 3)
+%!error gamrnd (ones(2,2), 2, [3, 2])
+%!error gamrnd (ones(2,2), 2, 2, 3)
+
--- a/scripts/statistics/distributions/geocdf.m
+++ b/scripts/statistics/distributions/geocdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,8 +19,8 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} geocdf (@var{x}, @var{p})
-## For each element of @var{x}, compute the CDF at @var{x} of the
-## geometric distribution with parameter @var{p}.
+## For each element of @var{x}, compute the cumulative distribution function
+## (CDF) at @var{x} of the geometric distribution with parameter @var{p}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -31,34 +32,58 @@
     print_usage ();
   endif
 
-  if (!isscalar (x) && !isscalar (p))
+  if (!isscalar (p))
     [retval, x, p] = common_size (x, p);
     if (retval > 0)
-      error ("geocdf: X and P must be of common size or scalar");
+      error ("geocdf: X and P must be of common size or scalars");
     endif
   endif
 
-  cdf = zeros (size (x));
+  if (iscomplex (x) || iscomplex (p))
+    error ("geocdf: X and P must not be complex");
+  endif
 
-  k = find (isnan (x) | !(p >= 0) | !(p <= 1));
-  if (any (k))
-    cdf(k) = NaN;
+  if (isa (x, "single") || isa (p, "single"))
+    cdf = zeros (size (x), "single");
+  else
+    cdf = zeros (size (x));
   endif
 
-  k = find ((x == Inf) & (p >= 0) & (p <= 1));
-  if (any (k))
-    cdf(k) = 1;
-  endif
+  k = isnan (x) | !(p >= 0) | !(p <= 1);
+  cdf(k) = NaN;
+
+  k = (x == Inf) & (p >= 0) & (p <= 1);
+  cdf(k) = 1;
 
-  k = find ((x >= 0) & (x < Inf) & (x == round (x)) & (p > 0) & (p <= 1));
-  if (any (k))
-    if (isscalar (x))
-      cdf(k) = 1 - ((1 - p(k)) .^ (x + 1));
-    elseif (isscalar (p))
-      cdf(k) = 1 - ((1 - p) .^ (x(k) + 1));
-    else
-      cdf(k) = 1 - ((1 - p(k)) .^ (x(k) + 1));
-    endif
+  k = (x >= 0) & (x < Inf) & (x == fix (x)) & (p > 0) & (p <= 1);
+  if (isscalar (p))
+    cdf(k) = 1 - ((1 - p) .^ (x(k) + 1));
+  else
+    cdf(k) = 1 - ((1 - p(k)) .^ (x(k) + 1));
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 1 Inf];
+%! y = [0 0.5 0.75 1];
+%!assert(geocdf (x, 0.5*ones(1,4)), y);
+%!assert(geocdf (x, 0.5), y);
+%!assert(geocdf (x, 0.5*[-1 NaN 4 1]), [NaN NaN NaN y(4)]);
+%!assert(geocdf ([x(1:2) NaN x(4)], 0.5), [y(1:2) NaN y(4)]);
+
+%% Test class of input preserved
+%!assert(geocdf ([x, NaN], 0.5), [y, NaN]);
+%!assert(geocdf (single([x, NaN]), 0.5), single([y, NaN]));
+%!assert(geocdf ([x, NaN], single(0.5)), single([y, NaN]));
+
+%% Test input validation
+%!error geocdf ()
+%!error geocdf (1)
+%!error geocdf (1,2,3)
+%!error geocdf (ones(3),ones(2))
+%!error geocdf (ones(2),ones(3))
+%!error geocdf (i, 2)
+%!error geocdf (2, i)
+
--- a/scripts/statistics/distributions/geoinv.m
+++ b/scripts/statistics/distributions/geoinv.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,8 +19,8 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} geoinv (@var{x}, @var{p})
-## For each element of @var{x}, compute the quantile at @var{x} of the
-## geometric distribution with parameter @var{p}.
+## For each element of @var{x}, compute the quantile (the inverse of
+## the CDF) at @var{x} of the geometric distribution with parameter @var{p}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -31,34 +32,54 @@
     print_usage ();
   endif
 
-  if (!isscalar (x) && !isscalar (p))
+  if (!isscalar (p))
     [retval, x, p] = common_size (x, p);
     if (retval > 0)
-      error ("geoinv: X and P must be of common size or scalar");
+      error ("geoinv: X and P must be of common size or scalars");
     endif
   endif
 
-  inv = zeros (size (x));
-
-  k = find (!(x >= 0) | !(x <= 1) | !(p >= 0) | !(p <= 1));
-  if (any (k))
-    inv(k) = NaN;
+  if (iscomplex (x) || iscomplex (p))
+    error ("geoinv: X and P must not be complex");
   endif
 
-  k = find ((x == 1) & (p >= 0) & (p <= 1));
-  if (any (k))
-    inv(k) = Inf;
+  if (isa (x, "single") || isa (p, "single"))
+    inv = NaN (size (x), "single");
+  else
+    inv = NaN (size (x));
   endif
 
-  k = find ((x > 0) & (x < 1) & (p > 0) & (p <= 1));
-  if (any (k))
-    if (isscalar (x))
-      inv(k) = max (ceil (log (1 - x) ./ log (1 - p(k))) - 1, 0);
-    elseif (isscalar (p))
-      inv(k) = max (ceil (log (1 - x(k)) / log (1 - p)) - 1, 0);
-    else
-      inv(k) = max (ceil (log (1 - x(k)) ./ log (1 - p(k))) - 1, 0);
-    endif
+  k = (x == 1) & (p >= 0) & (p <= 1);
+  inv(k) = Inf;
+
+  k = (x >= 0) & (x < 1) & (p > 0) & (p <= 1);
+  if (isscalar (p))
+    inv(k) = max (ceil (log (1 - x(k)) / log (1 - p)) - 1, 0);
+  else
+    inv(k) = max (ceil (log (1 - x(k)) ./ log (1 - p(k))) - 1, 0);
   endif
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.75 1 2];
+%!assert(geoinv (x, 0.5*ones(1,5)), [NaN 0 1 Inf NaN]);
+%!assert(geoinv (x, 0.5), [NaN 0 1 Inf NaN]);
+%!assert(geoinv (x, 0.5*[1 -1 NaN 4 1]), [NaN NaN NaN NaN NaN]);
+%!assert(geoinv ([x(1:2) NaN x(4:5)], 0.5), [NaN 0 NaN Inf NaN]);
+
+%% Test class of input preserved
+%!assert(geoinv ([x, NaN], 0.5), [NaN 0 1 Inf NaN NaN]);
+%!assert(geoinv (single([x, NaN]), 0.5), single([NaN 0 1 Inf NaN NaN]));
+%!assert(geoinv ([x, NaN], single(0.5)), single([NaN 0 1 Inf NaN NaN]));
+
+%% Test input validation
+%!error geoinv ()
+%!error geoinv (1)
+%!error geoinv (1,2,3)
+%!error geoinv (ones(3),ones(2))
+%!error geoinv (ones(2),ones(3))
+%!error geoinv (i, 2)
+%!error geoinv (2, i)
+
--- a/scripts/statistics/distributions/geopdf.m
+++ b/scripts/statistics/distributions/geopdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -31,35 +32,54 @@
     print_usage ();
   endif
 
-  if (!isscalar (x) && !isscalar (p))
+  if (!isscalar (p))
     [retval, x, p] = common_size (x, p);
     if (retval > 0)
-      error ("geopdf: X and P must be of common size or scalar");
+      error ("geopdf: X and P must be of common size or scalars");
     endif
   endif
 
-  pdf = zeros (size (x));
-
-  k = find (isnan (x) | !(p >= 0) | !(p <= 1));
-  if (any (k))
-    pdf(k) = NaN;
+  if (iscomplex (x) || iscomplex (p))
+    error ("geopdf: X and P must not be complex");
   endif
 
-  ## Just for the fun of it ...
-  k = find ((x == Inf) & (p == 0));
-  if (any (k))
-    pdf(k) = 1;
+  if (isa (x, "single") || isa (p, "single"))
+    pdf = zeros (size (x), "single");
+  else
+    pdf = zeros (size (x));
   endif
 
-  k = find ((x >= 0) & (x < Inf) & (x == round (x)) & (p > 0) & (p <= 1));
-  if (any (k))
-    if (isscalar (x))
-      pdf(k) = p(k) .* ((1 - p(k)) .^ x);
-    elseif (isscalar (p))
-      pdf(k) = p .* ((1 - p) .^ x(k));
-    else
-      pdf(k) = p(k) .* ((1 - p(k)) .^ x(k));
-    endif
+  k = isnan (x) | (x == Inf) | !(p >= 0) | !(p <= 1);
+  pdf(k) = NaN;
+
+  k = (x >= 0) & (x < Inf) & (x == fix (x)) & (p > 0) & (p <= 1);
+  if (isscalar (p))
+    pdf(k) = p * ((1 - p) .^ x(k));
+  else
+    pdf(k) = p(k) .* ((1 - p(k)) .^ x(k));
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 1 Inf];
+%! y = [0, 1/2, 1/4, NaN];
+%!assert(geopdf (x, 0.5*ones(1,4)), y);
+%!assert(geopdf (x, 0.5), y);
+%!assert(geopdf (x, 0.5*[-1 NaN 4 1]), [NaN NaN NaN y(4)]);
+%!assert(geopdf ([x, NaN], 0.5), [y, NaN]);
+
+%% Test class of input preserved
+%!assert(geopdf (single([x, NaN]), 0.5), single([y, NaN]), 5*eps("single"));
+%!assert(geopdf ([x, NaN], single(0.5)), single([y, NaN]), 5*eps("single"));
+
+%% Test input validation
+%!error geopdf ()
+%!error geopdf (1)
+%!error geopdf (1,2,3)
+%!error geopdf (ones(3),ones(2))
+%!error geopdf (ones(2),ones(3))
+%!error geopdf (i, 2)
+%!error geopdf (2, i)
+
--- a/scripts/statistics/distributions/geornd.m
+++ b/scripts/statistics/distributions/geornd.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,77 +18,108 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} geornd (@var{p}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} geornd (@var{p}, @var{sz})
-## Return an @var{r} by @var{c} matrix of random samples from the
-## geometric distribution with parameter @var{p}, which must be a scalar
-## or of size @var{r} by @var{c}.
+## @deftypefn  {Function File} {} geornd (@var{p})
+## @deftypefnx {Function File} {} geornd (@var{p}, @var{r})
+## @deftypefnx {Function File} {} geornd (@var{p}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} geornd (@var{p}, [@var{sz}])
+## Return a matrix of random samples from the geometric distribution with
+## parameter @var{p}.
 ##
-## If @var{r} and @var{c} are given create a matrix with @var{r} rows and
-## @var{c} columns.  Or if @var{sz} is a vector, create a matrix of size
-## @var{sz}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the size of
+## @var{p}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the geometric distribution
 
-function rnd = geornd (p, r, c)
-
-  if (nargin == 3)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("geornd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("geornd: C must be a positive integer");
-    endif
-    sz = [r, c];
+function rnd = geornd (p, varargin)
 
-    if (any (size (p) != 1)
-        && ((length (size (p)) != length (sz)) || any (size (p) != sz)))
-      error ("geornd: P must be scalar or of size [R, C]");
-    endif
-  elseif (nargin == 2)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
-    else
-      error ("geornd: R must be a positive integer or vector");
-    endif
-
-    if (any (size (p) != 1)
-        && ((length (size (p)) != length (sz)) || any (size (p) != sz)))
-      error ("geornd: n must be scalar or of size SZ");
-    endif
-  elseif (nargin == 1)
-    sz = size(p);
-  elseif (nargin != 1)
+  if (nargin < 1)
     print_usage ();
   endif
 
+  if (nargin == 1)
+    sz = size (p);
+  elseif (nargin == 2)
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
+    else
+      error ("geornd: dimension vector must be row vector of non-negative integers");
+    endif
+  elseif (nargin > 2)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("geornd: dimensions must be non-negative integers");
+    endif
+    sz = [varargin{:}];
+  endif
+
+  if (!isscalar (p) && !isequal (size (p), sz))
+    error ("geornd: P must be scalar or of size SZ");
+  endif
+
+  if (iscomplex (p))
+    error ("geornd: P must not be complex");
+  endif
+
+  if (isa (p, "single"))
+    cls = "single";
+  else
+    cls = "double";
+  endif
 
   if (isscalar (p))
-    if (p < 0 || p > 1)
-      rnd = NaN (sz);
+    if (p > 0 && p < 1);
+      rnd = floor (- rande (sz) ./ log (1 - p));
     elseif (p == 0)
-      rnd = Inf (sz);
-    elseif (p > 0 && p < 1);
-      rnd = floor (- rande(sz) ./ log (1 - p));
-    else
-      rnd = zeros (sz);
+      rnd = Inf (sz, cls);
+    elseif (p == 1)
+      rnd = zeros (sz, cls);
+    elseif (p < 0 || p > 1)
+      rnd = NaN (sz, cls);
     endif
   else
-    rnd = floor (- rande(sz) ./ log (1 - p));
+    rnd = floor (- rande (sz) ./ log (1 - p));
 
-    k = find (!(p >= 0) | !(p <= 1));
-    if (any (k))
-      rnd(k) = NaN (1, length (k));
-    endif
+    k = !(p >= 0) | !(p <= 1);
+  rnd(k) = NaN;
 
-    k = find (p == 0);
-    if (any (k))
-      rnd(k) = Inf (1, length (k));
-    endif
+    k = (p == 0);
+    rnd(k) = Inf;
   endif
 
 endfunction
+
+
+%!assert(size (geornd (0.5)), [1, 1]);
+%!assert(size (geornd (0.5*ones(2,1))), [2, 1]);
+%!assert(size (geornd (0.5*ones(2,2))), [2, 2]);
+%!assert(size (geornd (0.5, 3)), [3, 3]);
+%!assert(size (geornd (0.5, [4 1])), [4, 1]);
+%!assert(size (geornd (0.5, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (geornd (0.5)), "double");
+%!assert(class (geornd (single(0.5))), "single");
+%!assert(class (geornd (single([0.5 0.5]))), "single");
+%!assert(class (geornd (single(0))), "single");
+%!assert(class (geornd (single(1))), "single");
+
+%% Test input validation
+%!error geornd ()
+%!error geornd (ones(3),ones(2))
+%!error geornd (ones(2),ones(3))
+%!error geornd (i)
+%!error geornd (1, -1)
+%!error geornd (1, ones(2))
+%!error geornd (1, [2 -1 2])
+%!error geornd (ones(2,2), 2, 3)
+%!error geornd (ones(2,2), 3, 2)
+
--- a/scripts/statistics/distributions/hygecdf.m
+++ b/scripts/statistics/distributions/hygecdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1997-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -25,7 +26,7 @@
 ## replacement from a population of total size @var{t} containing
 ## @var{m} marked items.
 ##
-## The parameters @var{t}, @var{m}, and @var{n} must positive integers
+## The parameters @var{t}, @var{m}, and @var{n} must be positive integers
 ## with @var{m} and @var{n} not greater than @var{t}.
 ## @end deftypefn
 
@@ -39,14 +40,70 @@
   endif
 
   if (!isscalar (t) || !isscalar (m) || !isscalar (n))
-    error ("hygecdf: T, M and N must all be positive integers");
+    [retval, x, t, m, n] = common_size (x, t, m, n);
+    if (retval > 0)
+      error ("hygecdf: X, T, M, and N must be of common size or scalars");
+    endif
+  endif
+
+  if (iscomplex (x) || iscomplex (t) || iscomplex (m) || iscomplex (n))
+    error ("hygecdf: X, T, M, and N must not be complex");
   endif
 
-  if (t < 0 || m < 0 || n <= 0 || t != round (t) || m != round (m)
-      || n != round (n) || m > t || n > t)
+  if (isa (x, "single") || isa (t, "single") || isa (m, "single") || isa (n, "single"))
+    cdf = NaN (size (x), "single");
+  else
     cdf = NaN (size (x));
+  endif
+
+  ok = ((t >= 0) & (m >= 0) & (n > 0) & (m <= t) & (n <= t) &
+        (t == fix (t)) & (m == fix (m)) & (n == fix (n)));
+
+  if (isscalar (t))
+    if (ok)
+      cdf = discrete_cdf (x, 0 : n, hygepdf (0 : n, t, m, n));
+    endif
   else
-    cdf = discrete_cdf (x, 0 : n, hygepdf (0 : n, t, m, n));
+    for i = find (ok(:)')  # Must be row vector arg to for loop
+      v = 0 : n(i);
+      cdf(i) = discrete_cdf (x(i), v, hygepdf (v, t(i), m(i), n(i)));
+    endfor
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 1 2 3];
+%! y = [0 1/6 5/6 1 1];
+%!assert(hygecdf (x, 4*ones(1,5), 2, 2), y, eps);
+%!assert(hygecdf (x, 4, 2*ones(1,5), 2), y, eps);
+%!assert(hygecdf (x, 4, 2, 2*ones(1,5)), y, eps);
+%!assert(hygecdf (x, 4*[1 -1 NaN 1.1 1], 2, 2), [y(1) NaN NaN NaN y(5)], eps);
+%!assert(hygecdf (x, 4, 2*[1 -1 NaN 1.1 1], 2), [y(1) NaN NaN NaN y(5)], eps);
+%!assert(hygecdf (x, 4, 5, 2), [NaN NaN NaN NaN NaN]);
+%!assert(hygecdf (x, 4, 2, 2*[1 -1 NaN 1.1 1]), [y(1) NaN NaN NaN y(5)], eps);
+%!assert(hygecdf (x, 4, 2, 5), [NaN NaN NaN NaN NaN]);
+%!assert(hygecdf ([x(1:2) NaN x(4:5)], 4, 2, 2), [y(1:2) NaN y(4:5)], eps);
+
+%% Test class of input preserved
+%!assert(hygecdf ([x, NaN], 4, 2, 2), [y, NaN], eps);
+%!assert(hygecdf (single([x, NaN]), 4, 2, 2), single([y, NaN]), eps("single"));
+%!assert(hygecdf ([x, NaN], single(4), 2, 2), single([y, NaN]), eps("single"));
+%!assert(hygecdf ([x, NaN], 4, single(2), 2), single([y, NaN]), eps("single"));
+%!assert(hygecdf ([x, NaN], 4, 2, single(2)), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error hygecdf ()
+%!error hygecdf (1)
+%!error hygecdf (1,2)
+%!error hygecdf (1,2,3)
+%!error hygecdf (1,2,3,4,5)
+%!error hygecdf (ones(2), ones(3), 1, 1)
+%!error hygecdf (1, ones(2), ones(3), 1)
+%!error hygecdf (1, 1, ones(2), ones(3))
+%!error hygecdf (i, 2, 2, 2)
+%!error hygecdf (2, i, 2, 2)
+%!error hygecdf (2, 2, i, 2)
+%!error hygecdf (2, 2, 2, i)
+
--- a/scripts/statistics/distributions/hygeinv.m
+++ b/scripts/statistics/distributions/hygeinv.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1997-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,11 +19,14 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} hygeinv (@var{x}, @var{t}, @var{m}, @var{n})
-## For each element of @var{x}, compute the quantile at @var{x} of the
-## hypergeometric distribution with parameters @var{t}, @var{m}, and
-## @var{n}.
+## For each element of @var{x}, compute the quantile (the inverse of
+## the CDF) at @var{x} of the hypergeometric distribution with parameters
+## @var{t}, @var{m}, and @var{n}.  This is the probability of obtaining @var{x}
+## marked items when randomly drawing a sample of size @var{n} without
+## replacement from a population of total size @var{t} containing @var{m}
+## marked items.
 ##
-## The parameters @var{t}, @var{m}, and @var{n} must positive integers
+## The parameters @var{t}, @var{m}, and @var{n} must be positive integers
 ## with @var{m} and @var{n} not greater than @var{t}.
 ## @end deftypefn
 
@@ -36,14 +40,75 @@
   endif
 
   if (!isscalar (t) || !isscalar (m) || !isscalar (n))
-    error ("hygeinv: T, M and N must all be positive integers");
+    [retval, x, t, m, n] = common_size (x, t, m, n);
+    if (retval > 0)
+      error ("hygeinv: X, T, M, and N must be of common size or scalars");
+    endif
+  endif
+
+  if (iscomplex (x) || iscomplex (t) || iscomplex (m) || iscomplex (n))
+    error ("hygeinv: X, T, M, and N must not be complex");
+  endif
+
+  if (isa (x, "single") || isa (t, "single") || isa (m, "single") || isa (n, "single"))
+    inv = NaN (size (x), "single");
+  else
+    inv = NaN (size (x));
   endif
 
-  if (t < 0 || m < 0 || n <= 0 || t != round (t) || m != round (m)
-      || n != round (n) || m > t || n > t)
-    inv = NaN (size (x));
+  ok = ((t >= 0) & (m >= 0) & (n > 0) & (m <= t) & (n <= t) &
+        (t == fix (t)) & (m == fix (m)) & (n == fix (n)));
+
+  if (isscalar (t))
+    if (ok)
+      inv = discrete_inv (x, 0 : n, hygepdf (0 : n, t, m, n));
+      inv(x == 0) = 0;  # Hack to return correct value for start of distribution
+    endif
   else
-    inv = discrete_inv (x, 0 : n, hygepdf (0 : n, t, m, n));
+    for i = find (ok(:)')  # Must be row vector arg to for loop
+      v = 0 : n(i);
+      if (x(i) == 0)
+        inv(i) = 0;  # Hack to return correct value for start of distribution
+      else
+        inv(i) = discrete_inv (x(i), v, hygepdf (v, t(i), m(i), n(i)));
+      endif
+    endfor
   endif
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.5 1 2];
+%!assert(hygeinv (x, 4*ones(1,5), 2*ones(1,5), 2*ones(1,5)), [NaN 0 1 2 NaN]);
+%!assert(hygeinv (x, 4*ones(1,5), 2, 2), [NaN 0 1 2 NaN]);
+%!assert(hygeinv (x, 4, 2*ones(1,5), 2), [NaN 0 1 2 NaN]);
+%!assert(hygeinv (x, 4, 2, 2*ones(1,5)), [NaN 0 1 2 NaN]);
+%!assert(hygeinv (x, 4*[1 -1 NaN 1.1 1], 2, 2), [NaN NaN NaN NaN NaN]);
+%!assert(hygeinv (x, 4, 2*[1 -1 NaN 1.1 1], 2), [NaN NaN NaN NaN NaN]);
+%!assert(hygeinv (x, 4, 5, 2), [NaN NaN NaN NaN NaN]);
+%!assert(hygeinv (x, 4, 2, 2*[1 -1 NaN 1.1 1]), [NaN NaN NaN NaN NaN]);
+%!assert(hygeinv (x, 4, 2, 5), [NaN NaN NaN NaN NaN]);
+%!assert(hygeinv ([x(1:2) NaN x(4:5)], 4, 2, 2), [NaN 0 NaN 2 NaN]);
+
+%% Test class of input preserved
+%!assert(hygeinv ([x, NaN], 4, 2, 2), [NaN 0 1 2 NaN NaN]);
+%!assert(hygeinv (single([x, NaN]), 4, 2, 2), single([NaN 0 1 2 NaN NaN]));
+%!assert(hygeinv ([x, NaN], single(4), 2, 2), single([NaN 0 1 2 NaN NaN]));
+%!assert(hygeinv ([x, NaN], 4, single(2), 2), single([NaN 0 1 2 NaN NaN]));
+%!assert(hygeinv ([x, NaN], 4, 2, single(2)), single([NaN 0 1 2 NaN NaN]));
+
+%% Test input validation
+%!error hygeinv ()
+%!error hygeinv (1)
+%!error hygeinv (1,2)
+%!error hygeinv (1,2,3)
+%!error hygeinv (1,2,3,4,5)
+%!error hygeinv (ones(2), ones(3), 1, 1)
+%!error hygeinv (1, ones(2), ones(3), 1)
+%!error hygeinv (1, 1, ones(2), ones(3))
+%!error hygeinv (i, 2, 2, 2)
+%!error hygeinv (2, i, 2, 2)
+%!error hygeinv (2, 2, i, 2)
+%!error hygeinv (2, 2, 2, i)
+
--- a/scripts/statistics/distributions/hygepdf.m
+++ b/scripts/statistics/distributions/hygepdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1996-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -24,7 +25,8 @@
 ## when randomly drawing a sample of size @var{n} without replacement
 ## from a population of total size @var{t} containing @var{m} marked items.
 ##
-## The arguments must be of common size or scalar.
+## The parameters @var{t}, @var{m}, and @var{n} must be positive integers
+## with @var{m} and @var{n} not greater than @var{t}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -39,34 +41,72 @@
   if (!isscalar (t) || !isscalar (m) || !isscalar (n))
     [retval, x, t, m, n] = common_size (x, t, m, n);
     if (retval > 0)
-      error ("hygepdf: X, T, M, and N must be of common size or scalar");
+      error ("hygepdf: X, T, M, and N must be of common size or scalars");
     endif
   endif
 
-  pdf = zeros (size (x));
+  if (iscomplex (x) || iscomplex (t) || iscomplex (m) || iscomplex (n))
+    error ("hygepdf: X, T, M, and N must not be complex");
+  endif
+
+  if (isa (x, "single") || isa (t, "single") || isa (m, "single") || isa (n, "single"))
+    pdf = zeros (size (x), "single");
+  else
+    pdf = zeros (size (x));
+  endif
 
-  ## everything in i1 gives NaN
-  i1 = ((t < 0) | (m < 0) | (n <= 0) | (t != round (t)) |
-        (m != round (m)) | (n != round (n)) | (m > t) | (n > t));
-  ## everything in i2 gives 0 unless in i1
-  i2 = ((x != round (x)) | (x < 0) | (x > m) | (n < x) | (n-x > t-m));
-  k = find (i1);
-  if (any (k))
+  ## everything in nel gives NaN
+  nel = (isnan (x) | (t < 0) | (m < 0) | (n <= 0) | (m > t) | (n > t) |
+        (t != fix (t)) | (m != fix (m)) | (n != fix (n)));
+  ## everything in zel gives 0 unless in nel
+  zel = ((x != fix (x)) | (x < 0) | (x > m) | (n < x) | (n-x > t-m));
+
+  pdf(nel) = NaN;
+
+  k = !nel & !zel;
+  if (any (k(:)))
     if (isscalar (t) && isscalar (m) && isscalar (n))
-      pdf = NaN (size (x));
+      pdf(k) = (bincoeff (m, x(k)) .* bincoeff (t-m, n-x(k))
+                / bincoeff (t, n));
     else
-      pdf (k) = NaN;
-    endif
-  endif
-  k = find (!i1 & !i2);
-  if (any (k))
-    if (isscalar (t) && isscalar (m) && isscalar (n))
-      pdf (k) = (bincoeff (m, x(k)) .* bincoeff (t-m, n-x(k))
-                 / bincoeff (t, n));
-    else
-      pdf (k) = (bincoeff (m(k), x(k)) .* bincoeff (t(k)-m(k), n(k)-x(k))
-                 ./ bincoeff (t(k), n(k)));
+      pdf(k) = (bincoeff (m(k), x(k)) .* bincoeff (t(k)-m(k), n(k)-x(k))
+                ./ bincoeff (t(k), n(k)));
     endif
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 1 2 3];
+%! y = [0 1/6 4/6 1/6 0];
+%!assert(hygepdf (x, 4*ones(1,5), 2, 2), y);
+%!assert(hygepdf (x, 4, 2*ones(1,5), 2), y);
+%!assert(hygepdf (x, 4, 2, 2*ones(1,5)), y);
+%!assert(hygepdf (x, 4*[1 -1 NaN 1.1 1], 2, 2), [0 NaN NaN NaN 0]);
+%!assert(hygepdf (x, 4, 2*[1 -1 NaN 1.1 1], 2), [0 NaN NaN NaN 0]);
+%!assert(hygepdf (x, 4, 5, 2), [NaN NaN NaN NaN NaN]);
+%!assert(hygepdf (x, 4, 2, 2*[1 -1 NaN 1.1 1]), [0 NaN NaN NaN 0]);
+%!assert(hygepdf (x, 4, 2, 5), [NaN NaN NaN NaN NaN]);
+%!assert(hygepdf ([x, NaN], 4, 2, 2), [y, NaN], eps);
+
+%% Test class of input preserved
+%!assert(hygepdf (single([x, NaN]), 4, 2, 2), single([y, NaN]));
+%!assert(hygepdf ([x, NaN], single(4), 2, 2), single([y, NaN]));
+%!assert(hygepdf ([x, NaN], 4, single(2), 2), single([y, NaN]));
+%!assert(hygepdf ([x, NaN], 4, 2, single(2)), single([y, NaN]));
+
+%% Test input validation
+%!error hygepdf ()
+%!error hygepdf (1)
+%!error hygepdf (1,2)
+%!error hygepdf (1,2,3)
+%!error hygepdf (1,2,3,4,5)
+%!error hygepdf (1, ones(3),ones(2),ones(2))
+%!error hygepdf (1, ones(2),ones(3),ones(2))
+%!error hygepdf (1, ones(2),ones(2),ones(3))
+%!error hygepdf (i, 2, 2, 2)
+%!error hygepdf (2, i, 2, 2)
+%!error hygepdf (2, 2, i, 2)
+%!error hygepdf (2, 2, 2, i)
+
--- a/scripts/statistics/distributions/hygernd.m
+++ b/scripts/statistics/distributions/hygernd.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1997-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,81 +18,131 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} hygernd (@var{t}, @var{m}, @var{n}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} hygernd (@var{t}, @var{m}, @var{n}, @var{sz})
-## @deftypefnx {Function File} {} hygernd (@var{t}, @var{m}, @var{n})
-## Return an @var{r} by @var{c} matrix of random samples from the
-## hypergeometric distribution with parameters @var{t}, @var{m},
-## and @var{n}.
+## @deftypefn  {Function File} {} hygernd (@var{t}, @var{m}, @var{n})
+## @deftypefnx {Function File} {} hygernd (@var{t}, @var{m}, @var{n}, @var{r})
+## @deftypefnx {Function File} {} hygernd (@var{t}, @var{m}, @var{n}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} hygernd (@var{t}, @var{m}, @var{n}, [@var{sz}])
+## Return a matrix of random samples from the hypergeometric distribution
+## with parameters @var{t}, @var{m}, and @var{n}.
 ##
-## The parameters @var{t}, @var{m}, and @var{n} must positive integers
+## The parameters @var{t}, @var{m}, and @var{n} must be positive integers
 ## with @var{m} and @var{n} not greater than @var{t}.
 ##
-## The parameter @var{sz} must be scalar or a vector of matrix
-## dimensions.  If @var{sz} is scalar, then a @var{sz} by @var{sz}
-## matrix of random samples is generated.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the common size of
+## @var{t}, @var{m}, and @var{n}.
 ## @end deftypefn
 
-function rnd = hygernd (t, m, n, r, c)
+function rnd = hygernd (t, m, n, varargin)
 
-  if (nargin == 5)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("hygernd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("hygernd: C must be a positive integer");
-    endif
-    sz = [r, c];
-  elseif (nargin == 4)
-    if (isvector (r) && all (r > 0) && all (r == round (r)))
-      if (isscalar (r))
-        sz = [r, r];
-      else
-        sz = r(:)';
-      endif
-    else
-      error ("hygernd: R must be a vector of positive integers");
-    endif
-  elseif (nargin != 3)
+  if (nargin < 3)
     print_usage ();
   endif
 
   if (! isscalar (t) || ! isscalar (m) || ! isscalar (n))
     [retval, t, m, n] = common_size (t, m, n);
     if (retval > 0)
-      error ("hygernd: T, M and N must be of common size or scalar");
+      error ("hygernd: T, M, and N must be of common size or scalars");
+    endif
+  endif
+
+  if (iscomplex (t) || iscomplex (m) || iscomplex (n))
+    error ("hygernd: T, M, and N must not be complex");
+  endif
+
+  if (nargin == 3)
+    sz = size (t);
+  elseif (nargin == 4)
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
+    else
+      error ("hygernd: dimension vector must be row vector of non-negative integers");
+    endif
+  elseif (nargin > 4)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("hygernd: dimensions must be non-negative integers");
     endif
-    if (nargin > 3)
-      if (any (sz != size (t)))
-        error ("hygernd: T, M and N must have the same size as implied by R and C or must be scalar");
+    sz = [varargin{:}];
+  endif
+
+  if (!isscalar (t) && !isequal (size (t), sz))
+    error ("hygernd: T, M, and N must be scalar or of size SZ");
+  endif
+
+  if (isa (t, "single") || isa (m, "single") || isa (n, "single"))
+    cls = "single";
+  else
+    cls = "double";
+  endif
+
+  ok = ((t >= 0) & (m >= 0) & (n > 0) & (m <= t) & (n <= t) &
+        (t == fix (t)) & (m == fix (m)) & (n == fix (n)));
+
+  if (isscalar (t))
+    if (ok)
+      v = 0:n;
+      p = hygepdf (v, t, m, n);
+      rnd = v(lookup (cumsum (p(1:end-1)) / sum (p), rand (sz)) + 1);
+      rnd = reshape (rnd, sz);
+      if (strcmp (cls, "single"))
+        rnd = single (rnd);
       endif
     else
-      sz = size (t);
+      rnd = NaN (sz, cls);
     endif
-  elseif (nargin == 3)
-    sz = 1;
-  endif
-
-  ## NaN elements
-  ne = (! (t >= 0) | ! (m >= 0) | ! (n > 0) | ! (t == round (t)) | ! (m == round (m)) | ! (n == round (n)) | ! (m <= t) | ! (n <= t));
-
-  if (! isscalar (t))
-    rnd = zeros (sz);
-    rnd(ne) = NaN;
+  else
+    rnd = NaN (sz, cls);
     rn = rand (sz);
-    for i = find (! ne)
+    for i = find (ok(:)')  # Must be row vector arg to for loop
       v = 0 : n(i);
       p = hygepdf (v, t(i), m(i), n(i));
       rnd(i) = v(lookup (cumsum (p(1 : end-1)) / sum (p), rn(i)) + 1);
     endfor
-  else
-    if (ne)
-      rnd = NaN (sz);
-    else
-      v = 0:n;
-      p = hygepdf (v, t, m, n);
-      rnd = v(lookup (cumsum (p(1:end-1)) / sum (p), rand (sz)) + 1);
-    endif
   endif
 
 endfunction
+
+
+%!assert(size (hygernd (4,2,2)), [1, 1]);
+%!assert(size (hygernd (4*ones(2,1), 2,2)), [2, 1]);
+%!assert(size (hygernd (4*ones(2,2), 2,2)), [2, 2]);
+%!assert(size (hygernd (4, 2*ones(2,1), 2)), [2, 1]);
+%!assert(size (hygernd (4, 2*ones(2,2), 2)), [2, 2]);
+%!assert(size (hygernd (4, 2, 2*ones(2,1))), [2, 1]);
+%!assert(size (hygernd (4, 2, 2*ones(2,2))), [2, 2]);
+%!assert(size (hygernd (4, 2, 2, 3)), [3, 3]);
+%!assert(size (hygernd (4, 2, 2, [4 1])), [4, 1]);
+%!assert(size (hygernd (4, 2, 2, 4, 1)), [4, 1]);
+
+%!assert(class (hygernd (4,2,2)), "double");
+%!assert(class (hygernd (single(4),2,2)), "single");
+%!assert(class (hygernd (single([4 4]),2,2)), "single");
+%!assert(class (hygernd (4,single(2),2)), "single");
+%!assert(class (hygernd (4,single([2 2]),2)), "single");
+%!assert(class (hygernd (4,2,single(2))), "single");
+%!assert(class (hygernd (4,2,single([2 2]))), "single");
+
+%% Test input validation
+%!error hygernd ()
+%!error hygernd (1)
+%!error hygernd (1,2)
+%!error hygernd (ones(3),ones(2),ones(2), 2)
+%!error hygernd (ones(2),ones(3),ones(2), 2)
+%!error hygernd (ones(2),ones(2),ones(3), 2)
+%!error hygernd (i, 2, 2)
+%!error hygernd (2, i, 2)
+%!error hygernd (2, 2, i)
+%!error hygernd (4,2,2, -1)
+%!error hygernd (4,2,2, ones(2))
+%!error hygernd (4,2,2, [2 -1 2])
+%!error hygernd (4*ones(2),2,2, 3)
+%!error hygernd (4*ones(2),2,2, [3, 2])
+%!error hygernd (4*ones(2),2,2, 3, 2)
+
--- a/scripts/statistics/distributions/kolmogorov_smirnov_cdf.m
+++ b/scripts/statistics/distributions/kolmogorov_smirnov_cdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,16 +19,17 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} kolmogorov_smirnov_cdf (@var{x}, @var{tol})
-## Return the CDF at @var{x} of the Kolmogorov-Smirnov distribution,
+## Return the cumulative distribution function (CDF) at @var{x} of the 
+## Kolmogorov-Smirnov distribution,
 ## @tex
-## $$ Q(x) = \sum_{k=-\infty}^\infty (-1)^k \exp(-2 k^2 x^2) $$
+## $$ Q(x) = \sum_{k=-\infty}^\infty (-1)^k \exp (-2 k^2 x^2) $$
 ## @end tex
 ## @ifnottex
 ##
 ## @example
 ## @group
 ##          Inf
-## Q(x) =   SUM    (-1)^k exp(-2 k^2 x^2)
+## Q(x) =   SUM    (-1)^k exp (-2 k^2 x^2)
 ##        k = -Inf
 ## @end group
 ## @end example
@@ -61,8 +63,7 @@
     endif
   endif
 
-  n = numel (x);
-  if (n == 0)
+  if (numel (x) == 0)
     error ("kolmogorov_smirnov_cdf: X must not be empty");
   endif
 
@@ -70,10 +71,10 @@
 
   ind = find (x > 0);
   if (length (ind) > 0)
-    if (size(ind,2) < size(ind,1))
+    if (columns (ind) < rows (ind))
       y = x(ind.');
     else
-      y   = x(ind);
+      y = x(ind);
     endif
     K   = ceil (sqrt (- log (tol) / 2) / min (y));
     k   = (1:K)';
@@ -84,3 +85,11 @@
   endif
 
 endfunction
+
+
+%% Test input validation
+%!error kolmogorov_smirnov_cdf ()
+%!error kolmogorov_smirnov_cdf (1,2,3)
+%!error kolmogorov_smirnov_cdf (1, ones(2))
+%!error kolmogorov_smirnov_cdf ([], 1)
+
--- a/scripts/statistics/distributions/laplace_cdf.m
+++ b/scripts/statistics/distributions/laplace_cdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -31,21 +32,25 @@
     print_usage ();
   endif
 
-  cdf = zeros (size (x));
-
-  k = find (isnan (x));
-  if (any (k))
-    cdf(k) = NaN;
+  if (iscomplex (x))
+    error ("laplace_cdf: X must not be complex");
   endif
 
-  k = find (x == Inf);
-  if (any (k))
-    cdf(k) = 1;
-  endif
-
-  k = find ((x > -Inf) & (x < Inf));
-  if (any (k))
-    cdf(k) = (1 + sign (x(k)) .* (1 - exp (- abs (x(k))))) / 2;
-  endif
+  cdf = (1 + sign (x) .* (1 - exp (- abs (x)))) / 2;
 
 endfunction
+
+
+%!shared x,y
+%! x = [-Inf -log(2) 0 log(2) Inf];
+%! y = [0, 1/4, 1/2, 3/4, 1]; 
+%!assert(laplace_cdf ([x, NaN]), [y, NaN]);
+
+%% Test class of input preserved
+%!assert(laplace_cdf (single([x, NaN])), single([y, NaN]));
+
+%% Test input validation
+%!error laplace_cdf ()
+%!error laplace_cdf (1,2)
+%!error laplace_cdf (i)
+
--- a/scripts/statistics/distributions/laplace_inv.m
+++ b/scripts/statistics/distributions/laplace_inv.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -31,22 +32,33 @@
     print_usage ();
   endif
 
-  inv = -Inf (size (x));
+  if (iscomplex (x))
+    error ("laplace_inv: X must not be complex");
+  endif
 
-  k = find (isnan (x) | (x < 0) | (x > 1));
-  if (any (k))
-    inv(k) = NaN;
+  if (isa (x, "single"))
+    inv = NaN (size (x), "single");
+  else
+    inv = NaN (size (x));
   endif
 
-  k = find (x == 1);
-  if (any (k))
-    inv(k) = Inf;
-  endif
-
-  k = find ((x > 0) & (x < 1));
-  if (any (k))
-    inv(k) = ((x(k) < 1/2) .* log (2 * x(k))
-              - (x(k) > 1/2) .* log (2 * (1 - x(k))));
-  endif
+  k = (x >= 0) & (x <= 1);
+  inv(k) = ((x(k) < 1/2) .* log (2 * x(k))
+            - (x(k) > 1/2) .* log (2 * (1 - x(k))));
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.5 1 2];
+%!assert(laplace_inv (x), [NaN -Inf 0 Inf NaN]);
+
+%% Test class of input preserved
+%!assert(laplace_inv ([x, NaN]), [NaN -Inf 0 Inf NaN NaN]);
+%!assert(laplace_inv (single([x, NaN])), single([NaN -Inf 0 Inf NaN NaN]));
+
+%% Test input validation
+%!error laplace_inv ()
+%!error laplace_inv (1,2)
+%!error laplace_inv (i)
+
--- a/scripts/statistics/distributions/laplace_pdf.m
+++ b/scripts/statistics/distributions/laplace_pdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -30,17 +31,26 @@
   if (nargin != 1)
     print_usage ();
   endif
-
-  pdf = zeros (size (x));
-
-  k = find (isnan (x));
-  if (any (k))
-    pdf(k) = NaN;
+  
+  if (iscomplex (x))
+    error ("laplace_pdf: X must not be complex");
   endif
 
-  k = find ((x > -Inf) & (x < Inf));
-  if (any (k))
-    pdf(k) = exp (- abs (x(k))) / 2;
-  endif
+  pdf = exp (- abs (x)) / 2;
 
 endfunction
+
+
+%!shared x,y
+%! x = [-Inf -log(2) 0 log(2) Inf];
+%! y = [0, 1/4, 1/2, 1/4, 0]; 
+%!assert(laplace_pdf ([x, NaN]), [y, NaN]);
+
+%% Test class of input preserved
+%!assert(laplace_pdf (single([x, NaN])), single([y, NaN]));
+
+%% Test input validation
+%!error laplace_pdf ()
+%!error laplace_pdf (1,2)
+%!error laplace_pdf (i)
+
--- a/scripts/statistics/distributions/laplace_rnd.m
+++ b/scripts/statistics/distributions/laplace_rnd.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,40 +18,57 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} laplace_rnd (@var{r}, @var{c})
-## @deftypefnx {Function File} {} laplace_rnd (@var{sz});
-## Return an @var{r} by @var{c} matrix of random numbers from the
-## Laplace distribution.  Or if @var{sz} is a vector, create a matrix of
-## @var{sz}.
+## @deftypefn  {Function File} {} laplace_rnd (@var{r})
+## @deftypefnx {Function File} {} laplace_rnd (@var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} laplace_rnd ([@var{sz}])
+## Return a matrix of random samples from the Laplace distribution.
+##
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the Laplace distribution
 
-function rnd = laplace_rnd (r, c)
+function rnd = laplace_rnd (varargin)
 
-  if (nargin == 2)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("laplace_rnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("laplace_rnd: C must be a positive integer");
-    endif
-    sz = [r, c];
-  elseif (nargin == 1)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
-    else
-      error ("laplace_rnd: R must be a positive integer or vector");
-    endif
-  else
+  if (nargin < 1)
     print_usage ();
   endif
 
+  if (nargin == 1)
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1}(:)';
+    else
+      error ("laplace_rnd: dimension vector must be row vector of non-negative integers");
+    endif
+  elseif (nargin > 1)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("laplace_rnd: dimensions must be non-negative integers");
+    endif
+    sz = [varargin{:}];
+  endif
+
   tmp = rand (sz);
-  rnd = ((tmp < 1/2) .* log (2 * tmp)
-         - (tmp > 1/2) .* log (2 * (1 - tmp)));
+  rnd = (tmp < 1/2) .* log (2 * tmp) - (tmp > 1/2) .* log (2 * (1 - tmp));
 
 endfunction
+
+
+%!assert(size (laplace_rnd (3)), [3, 3]);
+%!assert(size (laplace_rnd ([4 1])), [4, 1]);
+%!assert(size (laplace_rnd (4,1)), [4, 1]);
+
+%% Test input validation
+%!error laplace_rnd ()
+%!error laplace_rnd (-1)
+%!error laplace_rnd (ones(2))
+%!error laplace_rnd ([2 -1 2])
+%!error laplace_rnd (1, ones(2))
+%!error laplace_rnd (1, -1)
+
--- a/scripts/statistics/distributions/logistic_cdf.m
+++ b/scripts/statistics/distributions/logistic_cdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,8 +19,8 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} logistic_cdf (@var{x})
-## For each component of @var{x}, compute the CDF at @var{x} of the
-## logistic distribution.
+## For each element of @var{x}, compute the cumulative distribution function
+## (CDF) at @var{x} of the logistic distribution.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -31,6 +32,25 @@
     print_usage ();
   endif
 
-  cdf = 1 ./ (1 + exp (- x));
+  if (iscomplex (x))
+    error ("logistic_cdf: X must not be complex");
+  endif
+
+  cdf = 1 ./ (1 + exp (-x));
 
 endfunction
+
+
+%!shared x,y
+%! x = [-Inf -log(3) 0 log(3) Inf];
+%! y = [0, 1/4, 1/2, 3/4, 1]; 
+%!assert(logistic_cdf ([x, NaN]), [y, NaN], eps);
+
+%% Test class of input preserved
+%!assert(logistic_cdf (single([x, NaN])), single([y, NaN]), eps ("single"));
+
+%% Test input validation
+%!error logistic_cdf ()
+%!error logistic_cdf (1,2)
+%!error logistic_cdf (i)
+
--- a/scripts/statistics/distributions/logistic_inv.m
+++ b/scripts/statistics/distributions/logistic_inv.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,7 +19,7 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} logistic_inv (@var{x})
-## For each component of @var{x}, compute the quantile (the inverse of
+## For each element of @var{x}, compute the quantile (the inverse of
 ## the CDF) at @var{x} of the logistic distribution.
 ## @end deftypefn
 
@@ -31,30 +32,38 @@
     print_usage ();
   endif
 
-  if (isa (x, 'single'))
-    inv = zeros (size (x), 'single');
-  else
-    inv = zeros (size (x));
+  if (iscomplex (x))
+    error ("logistic_inv: X must not be complex");
   endif
 
-  k = find ((x < 0) | (x > 1) | isnan (x));
-  if (any (k))
-    inv(k) = NaN;
+  if (isa (x, "single"))
+    inv = NaN (size (x), "single");
+  else
+    inv = NaN (size (x));
   endif
 
-  k = find (x == 0);
-  if (any (k))
-    inv(k) = -Inf;
-  endif
+  k = (x == 0);
+  inv(k) = -Inf;
 
-  k = find (x == 1);
-  if (any (k))
-    inv(k) = Inf;
-  endif
+  k = (x == 1);
+  inv(k) = Inf;
 
-  k = find ((x > 0) & (x < 1));
-  if (any (k))
-    inv (k) = - log (1 ./ x(k) - 1);
-  endif
+  k = (x > 0) & (x < 1);
+  inv(k) = - log (1 ./ x(k) - 1);
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.5 1 2];
+%!assert(logistic_inv (x), [NaN -Inf 0 Inf NaN]);
+
+%% Test class of input preserved
+%!assert(logistic_inv ([x, NaN]), [NaN -Inf 0 Inf NaN NaN]);
+%!assert(logistic_inv (single([x, NaN])), single([NaN -Inf 0 Inf NaN NaN]));
+
+%% Test input validation
+%!error logistic_inv ()
+%!error logistic_inv (1,2)
+%!error logistic_inv (i)
+
--- a/scripts/statistics/distributions/logistic_pdf.m
+++ b/scripts/statistics/distributions/logistic_pdf.m
@@ -18,7 +18,7 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} logistic_pdf (@var{x})
-## For each component of @var{x}, compute the PDF at @var{x} of the
+## For each element of @var{x}, compute the PDF at @var{x} of the
 ## logistic distribution.
 ## @end deftypefn
 
@@ -31,7 +31,26 @@
     print_usage ();
   endif
 
+  if (iscomplex (x))
+    error ("logistic_pdf: X must not be complex");
+  endif
+
   cdf = logistic_cdf (x);
   pdf = cdf .* (1 - cdf);
 
 endfunction
+
+
+%!shared x,y
+%! x = [-Inf -log(4) 0 log(4) Inf];
+%! y = [0, 0.16, 1/4, 0.16, 0]; 
+%!assert(logistic_pdf ([x, NaN]), [y, NaN], eps);
+
+%% Test class of input preserved
+%!assert(logistic_pdf (single([x, NaN])), single([y, NaN]), eps ("single"));
+
+%% Test input validation
+%!error logistic_pdf ()
+%!error logistic_pdf (1,2)
+%!error logistic_pdf (i)
+
--- a/scripts/statistics/distributions/logistic_rnd.m
+++ b/scripts/statistics/distributions/logistic_rnd.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,39 +18,56 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} logistic_rnd (@var{r}, @var{c})
-## @deftypefnx {Function File} {} logistic_rnd (@var{sz})
-## Return an @var{r} by @var{c} matrix of random numbers from the
-## logistic distribution.  Or if @var{sz} is a vector, create a matrix of
-## @var{sz}.
+## @deftypefn  {Function File} {} logistic_rnd (@var{r})
+## @deftypefnx {Function File} {} logistic_rnd (@var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} logistic_rnd ([@var{sz}])
+## Return a matrix of random samples from the logistic distribution.
+##
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the logistic distribution
 
-function rnd = logistic_rnd (r, c)
+function rnd = logistic_rnd (varargin)
 
+  if (nargin < 1)
+    print_usage ();
+  endif
 
-  if (nargin == 2)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("logistic_rnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("logistic_rnd: C must be a positive integer");
+  if (nargin == 1)
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
+    else
+      error ("logistic_rnd: dimension vector must be row vector of non-negative integers");
     endif
-    sz = [r, c];
-  elseif (nargin == 1)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
-    else
-      error ("logistic_rnd: R must be a positive integer or vector");
+  elseif (nargin > 1)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("logistic_rnd: dimensions must be non-negative integers");
     endif
-  else
-    print_usage ();
+    sz = [varargin{:}];
   endif
 
   rnd = - log (1 ./ rand (sz) - 1);
 
 endfunction
+
+
+%!assert(size (logistic_rnd (3)), [3, 3]);
+%!assert(size (logistic_rnd ([4 1])), [4, 1]);
+%!assert(size (logistic_rnd (4,1)), [4, 1]);
+
+%% Test input validation
+%!error logistic_rnd ()
+%!error logistic_rnd (-1)
+%!error logistic_rnd (ones(2))
+%!error logistic_rnd ([2 -1 2])
+%!error logistic_rnd (1, ones(2))
+%!error logistic_rnd (1, -1)
+
--- a/scripts/statistics/distributions/logncdf.m
+++ b/scripts/statistics/distributions/logncdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,7 +18,8 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} logncdf (@var{x}, @var{mu}, @var{sigma})
+## @deftypefn  {Function File} {} logncdf (@var{x})
+## @deftypefnx {Function File} {} logncdf (@var{x}, @var{mu}, @var{sigma})
 ## For each element of @var{x}, compute the cumulative distribution
 ## function (CDF) at @var{x} of the lognormal distribution with
 ## parameters @var{mu} and @var{sigma}.  If a random variable follows this
@@ -30,48 +32,69 @@
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: CDF of the log normal distribution
 
-function cdf = logncdf (x, mu, sigma)
+function cdf = logncdf (x, mu = 0, sigma = 1)
 
-  if (! ((nargin == 1) || (nargin == 3)))
+  if (nargin != 1 && nargin != 3)
     print_usage ();
   endif
 
-  if (nargin == 1)
-    mu = 0;
-    sigma = 1;
-  endif
-
-  ## The following "straightforward" implementation unfortunately does
-  ## not work (because exp (Inf) -> NaN etc):
-  ## cdf = normal_cdf (log (x), log (mu), sigma);
-  ## Hence ...
-
   if (!isscalar (mu) || !isscalar (sigma))
     [retval, x, mu, sigma] = common_size (x, mu, sigma);
     if (retval > 0)
-      error ("logncdf: X, MU and SIGMA must be of common size or scalars");
+      error ("logncdf: X, MU, and SIGMA must be of common size or scalars");
     endif
   endif
 
-  cdf = zeros (size (x));
+  if (iscomplex (x) || iscomplex (mu) || iscomplex (sigma))
+    error ("logncdf: X, MU, and SIGMA must not be complex");
+  endif
 
-  k = find (isnan (x) | !(sigma > 0) | !(sigma < Inf));
-  if (any (k))
-    cdf(k) = NaN;
+  if (isa (x, "single") || isa (mu, "single") || isa (sigma, "single"))
+    cdf = zeros (size (x), "single");
+  else
+    cdf = zeros (size (x));
   endif
 
-  k = find ((x == Inf) & (sigma > 0) & (sigma < Inf));
-  if (any (k))
-    cdf(k) = 1;
-  endif
+  k = isnan (x) | !(sigma > 0) | !(sigma < Inf);
+  cdf(k) = NaN;
+
+  k = (x == Inf) & (sigma > 0) & (sigma < Inf);
+  cdf(k) = 1;
 
-  k = find ((x > 0) & (x < Inf) & (sigma > 0) & (sigma < Inf));
-  if (any (k))
-    if (isscalar (mu) && isscalar (sigma))
-      cdf(k) = stdnormal_cdf ((log (x(k)) - mu) / sigma);
-    else
-      cdf(k) = stdnormal_cdf ((log (x(k)) - mu(k)) ./ sigma(k));
-    endif
+  k = (x > 0) & (x < Inf) & (sigma > 0) & (sigma < Inf);
+  if (isscalar (mu) && isscalar (sigma))
+    cdf(k) = stdnormal_cdf ((log (x(k)) - mu) / sigma);
+  else
+    cdf(k) = stdnormal_cdf ((log (x(k)) - mu(k)) ./ sigma(k));
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 1 e Inf];
+%! y = [0, 0, 0.5, 1/2+1/2*erf(1/2), 1];
+%!assert(logncdf (x, zeros(1,5), sqrt(2)*ones(1,5)), y);
+%!assert(logncdf (x, 0, sqrt(2)*ones(1,5)), y);
+%!assert(logncdf (x, zeros(1,5), sqrt(2)), y);
+%!assert(logncdf (x, [0 1 NaN 0 1], sqrt(2)), [0 0 NaN y(4:5)]);
+%!assert(logncdf (x, 0, sqrt(2)*[0 NaN Inf 1 1]), [NaN NaN NaN y(4:5)]);
+%!assert(logncdf ([x(1:3) NaN x(5)], 0, sqrt(2)), [y(1:3) NaN y(5)]);
+
+%% Test class of input preserved
+%!assert(logncdf ([x, NaN], 0, sqrt(2)), [y, NaN]);
+%!assert(logncdf (single([x, NaN]), 0, sqrt(2)), single([y, NaN]), eps("single"));
+%!assert(logncdf ([x, NaN], single(0), sqrt(2)), single([y, NaN]), eps("single"));
+%!assert(logncdf ([x, NaN], 0, single(sqrt(2))), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error logncdf ()
+%!error logncdf (1,2)
+%!error logncdf (1,2,3,4)
+%!error logncdf (ones(3),ones(2),ones(2))
+%!error logncdf (ones(2),ones(3),ones(2))
+%!error logncdf (ones(2),ones(2),ones(3))
+%!error logncdf (i, 2, 2)
+%!error logncdf (2, i, 2)
+%!error logncdf (2, 2, i)
+
--- a/scripts/statistics/distributions/logninv.m
+++ b/scripts/statistics/distributions/logninv.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,7 +18,8 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} logninv (@var{x}, @var{mu}, @var{sigma})
+## @deftypefn  {Function File} {} logninv (@var{x})
+## @deftypefnx {Function File} {} logninv (@var{x}, @var{mu}, @var{sigma})
 ## For each element of @var{x}, compute the quantile (the inverse of the
 ## CDF) at @var{x} of the lognormal distribution with parameters @var{mu}
 ## and @var{sigma}.  If a random variable follows this distribution, its
@@ -30,48 +32,68 @@
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Quantile function of the log normal distribution
 
-function inv = logninv (x, mu, sigma)
+function inv = logninv (x, mu = 0, sigma = 1)
 
-  if (! ((nargin == 1) || (nargin == 3)))
+  if (nargin != 1 && nargin != 3)
     print_usage ();
   endif
 
-  if (nargin == 1)
-    mu = 0;
-    sigma = 1;
-  endif
-
-  ## The following "straightforward" implementation unfortunately does
-  ## not work (because exp (Inf) -> NaN):
-  ## inv = exp (norminv (x, mu, sigma));
-  ## Hence ...
-
   if (!isscalar (mu) || !isscalar (sigma))
     [retval, x, mu, sigma] = common_size (x, mu, sigma);
     if (retval > 0)
-      error ("logninv: X, MU and SIGMA must be of common size or scalars");
+      error ("logninv: X, MU, and SIGMA must be of common size or scalars");
     endif
   endif
 
-  inv = zeros (size (x));
+  if (iscomplex (x) || iscomplex (mu) || iscomplex (sigma))
+    error ("logninv: X, MU, and SIGMA must not be complex");
+  endif
 
-  k = find (!(x >= 0) | !(x <= 1) | !(sigma > 0) | !(sigma < Inf));
-  if (any (k))
-    inv(k) = NaN;
+  if (isa (x, "single") || isa (mu, "single") || isa (sigma, "single"))
+    inv = NaN (size (x), "single");
+  else
+    inv = NaN (size (x));
   endif
 
-  k = find ((x == 1) & (sigma > 0) & (sigma < Inf));
-  if (any (k))
-    inv(k) = Inf;
-  endif
+  k = !(x >= 0) | !(x <= 1) | !(sigma > 0) | !(sigma < Inf);
+  inv(k) = NaN;
+
+  k = (x == 1) & (sigma > 0) & (sigma < Inf);
+  inv(k) = Inf;
 
-  k = find ((x > 0) & (x < 1) & (sigma > 0) & (sigma < Inf));
-  if (any (k))
-    if (isscalar (mu) && isscalar (sigma))
-      inv(k) = exp (mu) .* exp (sigma .* stdnormal_inv (x(k)));
-    else
-      inv(k) = exp (mu(k)) .* exp (sigma(k) .* stdnormal_inv (x(k)));
-    endif
+  k = (x >= 0) & (x < 1) & (sigma > 0) & (sigma < Inf);
+  if (isscalar (mu) && isscalar (sigma))
+    inv(k) = exp (mu) .* exp (sigma .* stdnormal_inv (x(k)));
+  else
+    inv(k) = exp (mu(k)) .* exp (sigma(k) .* stdnormal_inv (x(k)));
   endif
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.5 1 2];
+%!assert(logninv (x, ones(1,5), ones(1,5)), [NaN 0 e Inf NaN]);
+%!assert(logninv (x, 1, ones(1,5)), [NaN 0 e Inf NaN]);
+%!assert(logninv (x, ones(1,5), 1), [NaN 0 e Inf NaN]);
+%!assert(logninv (x, [1 1 NaN 0 1], 1), [NaN 0 NaN Inf NaN]);
+%!assert(logninv (x, 1, [1 0 NaN Inf 1]), [NaN NaN NaN NaN NaN]);
+%!assert(logninv ([x(1:2) NaN x(4:5)], 1, 2), [NaN 0 NaN Inf NaN]);
+
+%% Test class of input preserved
+%!assert(logninv ([x, NaN], 1, 1), [NaN 0 e Inf NaN NaN]);
+%!assert(logninv (single([x, NaN]), 1, 1), single([NaN 0 e Inf NaN NaN]));
+%!assert(logninv ([x, NaN], single(1), 1), single([NaN 0 e Inf NaN NaN]));
+%!assert(logninv ([x, NaN], 1, single(1)), single([NaN 0 e Inf NaN NaN]));
+
+%% Test input validation
+%!error logninv ()
+%!error logninv (1,2)
+%!error logninv (1,2,3,4)
+%!error logninv (ones(3),ones(2),ones(2))
+%!error logninv (ones(2),ones(3),ones(2))
+%!error logninv (ones(2),ones(2),ones(3))
+%!error logninv (i, 2, 2)
+%!error logninv (2, i, 2)
+%!error logninv (2, 2, i)
+
--- a/scripts/statistics/distributions/lognpdf.m
+++ b/scripts/statistics/distributions/lognpdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,7 +18,8 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} lognpdf (@var{x}, @var{mu}, @var{sigma})
+## @deftypefn  {Function File} {} lognpdf (@var{x})
+## @deftypefnx {Function File} {} lognpdf (@var{x}, @var{mu}, @var{sigma})
 ## For each element of @var{x}, compute the probability density function
 ## (PDF) at @var{x} of the lognormal distribution with parameters
 ## @var{mu} and @var{sigma}.  If a random variable follows this distribution,
@@ -30,43 +32,65 @@
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: PDF of the log normal distribution
 
-function pdf = lognpdf (x, mu, sigma)
+function pdf = lognpdf (x, mu = 0, sigma = 1)
 
-  if (! ((nargin == 1) || (nargin == 3)))
+  if (nargin != 1 && nargin != 3)
     print_usage ();
   endif
 
-  if (nargin == 1)
-    mu = 0;
-    sigma = 1;
-  endif
-
-  ## The following "straightforward" implementation unfortunately does
-  ## not work for the special cases (Inf, ...)
-  ## pdf = (x > 0) ./ x .* normpdf (log (x), mu, sigma);
-  ## Hence ...
-
   if (!isscalar (mu) || !isscalar (sigma))
     [retval, x, mu, sigma] = common_size (x, mu, sigma);
     if (retval > 0)
-      error ("lognpdf: X, MU and SIGMA must be of common size or scalars");
+      error ("lognpdf: X, MU, and SIGMA must be of common size or scalars");
     endif
   endif
 
-  pdf = zeros (size (x));
-
-  k = find (isnan (x) | !(sigma > 0) | !(sigma < Inf));
-  if (any (k))
-    pdf(k) = NaN;
+  if (iscomplex (x) || iscomplex (mu) || iscomplex (sigma))
+    error ("lognpdf: X, MU, and SIGMA must not be complex");
   endif
 
-  k = find ((x > 0) & (x < Inf) & (sigma > 0) & (sigma < Inf));
-  if (any (k))
-    if (isscalar (mu) && isscalar (sigma))
-      pdf(k) = normpdf (log (x(k)), mu, sigma) ./ x(k);
-    else
-      pdf(k) = normpdf (log (x(k)), mu(k), sigma(k)) ./ x(k);
-    endif
+  if (isa (x, "single") || isa (mu, "single") || isa (sigma, "single"))
+    pdf = zeros (size (x), "single");
+  else
+    pdf = zeros (size (x));
+  endif
+
+  k = isnan (x) | !(sigma > 0) | !(sigma < Inf);
+  pdf(k) = NaN;
+
+  k = (x > 0) & (x < Inf) & (sigma > 0) & (sigma < Inf);
+  if (isscalar (mu) && isscalar (sigma))
+    pdf(k) = normpdf (log (x(k)), mu, sigma) ./ x(k);
+  else
+    pdf(k) = normpdf (log (x(k)), mu(k), sigma(k)) ./ x(k);
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 e Inf];
+%! y = [0, 0, 1/(e*sqrt(2*pi)) * exp(-1/2), 0];
+%!assert(lognpdf (x, zeros(1,4), ones(1,4)), y, eps);
+%!assert(lognpdf (x, 0, ones(1,4)), y, eps);
+%!assert(lognpdf (x, zeros(1,4), 1), y, eps);
+%!assert(lognpdf (x, [0 1 NaN 0], 1), [0 0 NaN y(4)], eps);
+%!assert(lognpdf (x, 0, [0 NaN Inf 1]), [NaN NaN NaN y(4)], eps);
+%!assert(lognpdf ([x, NaN], 0, 1), [y, NaN], eps);
+
+%% Test class of input preserved
+%!assert(lognpdf (single([x, NaN]), 0, 1), single([y, NaN]), eps("single"));
+%!assert(lognpdf ([x, NaN], single(0), 1), single([y, NaN]), eps("single"));
+%!assert(lognpdf ([x, NaN], 0, single(1)), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error lognpdf ()
+%!error lognpdf (1,2)
+%!error lognpdf (1,2,3,4)
+%!error lognpdf (ones(3),ones(2),ones(2))
+%!error lognpdf (ones(2),ones(3),ones(2))
+%!error lognpdf (ones(2),ones(2),ones(3))
+%!error lognpdf (i, 2, 2)
+%!error lognpdf (2, i, 2)
+%!error lognpdf (2, 2, i)
+
--- a/scripts/statistics/distributions/lognrnd.m
+++ b/scripts/statistics/distributions/lognrnd.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,76 +18,115 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} lognrnd (@var{mu}, @var{sigma}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} lognrnd (@var{mu}, @var{sigma}, @var{sz})
-## Return an @var{r} by @var{c} matrix of random samples from the
-## lognormal distribution with parameters @var{mu} and @var{sigma}.  Both
-## @var{mu} and @var{sigma} must be scalar or of size @var{r} by @var{c}.
-## Or if @var{sz} is a vector, create a matrix of size @var{sz}.
+## @deftypefn  {Function File} {} lognrnd (@var{mu}, @var{sigma})
+## @deftypefnx {Function File} {} lognrnd (@var{mu}, @var{sigma}, @var{r})
+## @deftypefnx {Function File} {} lognrnd (@var{mu}, @var{sigma}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} lognrnd (@var{mu}, @var{sigma}, [@var{sz}])
+## Return a matrix of random samples from the lognormal distribution with
+## parameters @var{mu} and @var{sigma}.
 ##
-## If @var{r} and @var{c} are omitted, the size of the result matrix is
-## the common size of @var{mu} and @var{sigma}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the common size of
+## @var{mu} and @var{sigma}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the log normal distribution
 
-function rnd = lognrnd (mu, sigma, r, c)
+function rnd = lognrnd (mu, sigma, varargin)
 
-  if (nargin > 1)
-    if (!isscalar(mu) || !isscalar(sigma))
-      [retval, mu, sigma] = common_size (mu, sigma);
-      if (retval > 0)
-        error ("lognrnd: MU and SIGMA must be of common size or scalar");
-      endif
+  if (nargin < 2)
+    print_usage ();
+  endif
+
+  if (!isscalar (mu) || !isscalar (sigma))
+    [retval, mu, sigma] = common_size (mu, sigma);
+    if (retval > 0)
+      error ("lognrnd: MU and SIGMA must be of common size or scalars");
     endif
   endif
 
-  if (nargin == 4)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("lognrnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("lognrnd: C must be a positive integer");
-    endif
-    sz = [r, c];
+  if (iscomplex (mu) || iscomplex (sigma))
+    error ("lognrnd: MU and SIGMA must not be complex");
+  endif
 
-    if (any (size (mu) != 1)
-        && ((length (size (mu)) != length (sz)) || any (size (mu) != sz)))
-      error ("lognrnd: MU and SIGMA must be scalar or of size [R, C]");
-    endif
-
+  if (nargin == 2)
+    sz = size (mu);
   elseif (nargin == 3)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
     else
-      error ("lognrnd: R must be a positive integer or vector");
+      error ("lognrnd: dimension vector must be row vector of non-negative integers");
     endif
+  elseif (nargin > 3)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("lognrnd: dimensions must be non-negative integers");
+    endif
+    sz = [varargin{:}];
+  endif
 
-    if (any (size (mu) != 1)
-        && ((length (size (mu)) != length (sz)) || any (size (mu) != sz)))
-      error ("lognrnd: MU and SIGMA must be scalar or of size SZ");
-    endif
-  elseif (nargin == 2)
-    sz = size(mu);
+  if (!isscalar (mu) && !isequal (size (mu), sz))
+    error ("lognrnd: MU and SIGMA must be scalar or of size SZ");
+  endif
+
+  if (isa (mu, "single") || isa (sigma, "single"))
+    cls = "single";
   else
-    print_usage ();
+    cls = "double";
   endif
 
   if (isscalar (mu) && isscalar (sigma))
-    if  (!(sigma > 0) || !(sigma < Inf))
-      rnd = NaN (sz);
+    if ((sigma > 0) && (sigma < Inf))
+      rnd = exp (mu + sigma * randn (sz));
     else
-      rnd = exp(mu + sigma .* randn (sz));
+      rnd = NaN (sz, cls);
     endif
   else
     rnd = exp (mu + sigma .* randn (sz));
-    k = find ((sigma < 0) | (sigma == Inf));
-    if (any (k))
-      rnd(k) = NaN;
-    endif
+
+    k = (sigma < 0) | (sigma == Inf);
+    rnd(k) = NaN;
   endif
 
 endfunction
+
+
+%!assert(size (lognrnd (1,2)), [1, 1]);
+%!assert(size (lognrnd (ones(2,1), 2)), [2, 1]);
+%!assert(size (lognrnd (ones(2,2), 2)), [2, 2]);
+%!assert(size (lognrnd (1, 2*ones(2,1))), [2, 1]);
+%!assert(size (lognrnd (1, 2*ones(2,2))), [2, 2]);
+%!assert(size (lognrnd (1, 2, 3)), [3, 3]);
+%!assert(size (lognrnd (1, 2, [4 1])), [4, 1]);
+%!assert(size (lognrnd (1, 2, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (lognrnd (1, 2)), "double");
+%!assert(class (lognrnd (single(1), 2)), "single");
+%!assert(class (lognrnd (single([1 1]), 2)), "single");
+%!assert(class (lognrnd (1, single(2))), "single");
+%!assert(class (lognrnd (1, single([2 2]))), "single");
+
+%% Test input validation
+%!error lognrnd ()
+%!error lognrnd (1)
+%!error lognrnd (ones(3),ones(2))
+%!error lognrnd (ones(2),ones(3))
+%!error lognrnd (i, 2)
+%!error lognrnd (2, i)
+%!error lognrnd (1,2, -1)
+%!error lognrnd (1,2, ones(2))
+%!error lognrnd (1, 2, [2 -1 2])
+%!error lognrnd (1,2, 1, ones(2))
+%!error lognrnd (1,2, 1, -1)
+%!error lognrnd (ones(2,2), 2, 3)
+%!error lognrnd (ones(2,2), 2, [3, 2])
+%!error lognrnd (ones(2,2), 2, 2, 3)
+
--- a/scripts/statistics/distributions/nbincdf.m
+++ b/scripts/statistics/distributions/nbincdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,9 +19,13 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} nbincdf (@var{x}, @var{n}, @var{p})
-## For each element of @var{x}, compute the CDF at x of the Pascal
-## (negative binomial) distribution with parameters @var{n} and @var{p}.
+## For each element of @var{x}, compute the cumulative distribution function
+## (CDF) at @var{x} of the negative binomial distribution with
+## parameters @var{n} and @var{p}.
 ##
+## When @var{n} is integer this is the Pascal distribution.  When
+## @var{n} is extended to real numbers this is the Polya distribution.
+## 
 ## The number of failures in a Bernoulli experiment with success
 ## probability @var{p} before the @var{n}-th success follows this
 ## distribution.
@@ -35,58 +40,66 @@
     print_usage ();
   endif
 
-  if (!isscalar(n) || !isscalar(p))
+  if (!isscalar (n) || !isscalar (p))
     [retval, x, n, p] = common_size (x, n, p);
     if (retval > 0)
-      error ("nbincdf: X, N and P must be of common size or scalar");
+      error ("nbincdf: X, N, and P must be of common size or scalars");
     endif
   endif
 
-  cdf = zeros (size (x));
-
-  k = find (isnan (x) | (n < 1) | (n == Inf) | (n != round (n))
-            | (p < 0) | (p > 1));
-  if (any (k))
-    cdf(k) = NaN;
+  if (iscomplex (x) || iscomplex (n) || iscomplex (p))
+    error ("nbincdf: X, N, and P must not be complex");
   endif
 
-  k = find ((x == Inf) & (n > 0) & (n < Inf) & (n == round (n))
-            & (p >= 0) & (p <= 1));
-  if (any (k))
-    cdf(k) = 1;
+  if (isa (x, "single") || isa (n, "single") || isa (p, "single"))
+    cdf = zeros (size (x), "single");
+  else
+    cdf = zeros (size (x));
   endif
 
-  k = find ((x >= 0) & (x < Inf) & (x == round (x)) & (n > 0)
-            & (n < Inf) & (n == round (n)) & (p > 0) & (p <= 1));
-  if (any (k))
-    ## Does anyone know a better way to do the summation?
-    m = zeros (size (k));
-    x = floor (x(k));
-    y = cdf(k);
-    if (isscalar (n) && isscalar (p))
-      while (1)
-        l = find (m <= x);
-        if (any (l))
-          y(l) = y(l) + nbinpdf (m(l), n, p);
-          m(l) = m(l) + 1;
-        else
-          break;
-        endif
-      endwhile
-    else
-      n = n(k);
-      p = p(k);
-      while (1)
-        l = find (m <= x);
-        if (any (l))
-          y(l) = y(l) + nbinpdf (m(l), n(l), p(l));
-          m(l) = m(l) + 1;
-        else
-          break;
-        endif
-      endwhile
-    endif
-    cdf(k) = y;
+  k = (isnan (x) | isnan (n) | (n < 1) | (n == Inf) 
+       | (p < 0) | (p > 1) | isnan (p));
+  cdf(k) = NaN;
+
+  k = (x == Inf) & (n > 0) & (n < Inf) & (p >= 0) & (p <= 1);
+  cdf(k) = 1;
+
+  k = ((x >= 0) & (x < Inf) & (x == fix (x))
+       & (n > 0) & (n < Inf) & (p > 0) & (p <= 1));
+  if (isscalar (n) && isscalar (p))
+    cdf(k) = 1 - betainc (1-p, x(k)+1, n);
+  else
+    cdf(k) = 1 - betainc (1-p(k), x(k)+1, n(k));
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 1 2 Inf];
+%! y = [0 1/2 3/4 7/8 1];
+%!assert(nbincdf (x, ones(1,5), 0.5*ones(1,5)), y);
+%!assert(nbincdf (x, 1, 0.5*ones(1,5)), y);
+%!assert(nbincdf (x, ones(1,5), 0.5), y);
+%!assert(nbincdf ([x(1:3) 0 x(5)], [0 1 NaN 1.5 Inf], 0.5), [NaN 1/2 NaN nbinpdf(0,1.5,0.5) NaN], eps);
+%!assert(nbincdf (x, 1, 0.5*[-1 NaN 4 1 1]), [NaN NaN NaN y(4:5)]);
+%!assert(nbincdf ([x(1:2) NaN x(4:5)], 1, 0.5), [y(1:2) NaN y(4:5)]);
+
+%% Test class of input preserved
+%!assert(nbincdf ([x, NaN], 1, 0.5), [y, NaN]);
+%!assert(nbincdf (single([x, NaN]), 1, 0.5), single([y, NaN]));
+%!assert(nbincdf ([x, NaN], single(1), 0.5), single([y, NaN]));
+%!assert(nbincdf ([x, NaN], 1, single(0.5)), single([y, NaN]));
+
+%% Test input validation
+%!error nbincdf ()
+%!error nbincdf (1)
+%!error nbincdf (1,2)
+%!error nbincdf (1,2,3,4)
+%!error nbincdf (ones(3),ones(2),ones(2))
+%!error nbincdf (ones(2),ones(3),ones(2))
+%!error nbincdf (ones(2),ones(2),ones(3))
+%!error nbincdf (i, 2, 2)
+%!error nbincdf (2, i, 2)
+%!error nbincdf (2, 2, i)
+
--- a/scripts/statistics/distributions/nbininv.m
+++ b/scripts/statistics/distributions/nbininv.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,10 +19,13 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} nbininv (@var{x}, @var{n}, @var{p})
-## For each element of @var{x}, compute the quantile at @var{x} of the
-## Pascal (negative binomial) distribution with parameters @var{n} and
-## @var{p}.
+## For each element of @var{x}, compute the quantile (the inverse of
+## the CDF) at @var{x} of the negative binomial distribution
+## with parameters @var{n} and @var{p}.
 ##
+## When @var{n} is integer this is the Pascal distribution.  When
+## @var{n} is extended to real numbers this is the Polya distribution.
+## 
 ## The number of failures in a Bernoulli experiment with success
 ## probability @var{p} before the @var{n}-th success follows this
 ## distribution.
@@ -36,58 +40,89 @@
     print_usage ();
   endif
 
-  if (!isscalar(n) || !isscalar(p))
+  if (!isscalar (n) || !isscalar (p))
     [retval, x, n, p] = common_size (x, n, p);
     if (retval > 0)
-      error ("nbininv: X, N and P must be of common size or scalar");
+      error ("nbininv: X, N, and P must be of common size or scalars");
     endif
   endif
 
-  inv = zeros (size (x));
-
-  k = find (isnan (x) | (x < 0) | (x > 1) | (n < 1) | (n == Inf)
-            | (n != round (n)) | (p < 0) | (p > 1));
-  if (any (k))
-    inv(k) = NaN;
+  if (iscomplex (x) || iscomplex (n) || iscomplex (p))
+    error ("nbininv: X, N, and P must not be complex");
   endif
 
-  k = find ((x == 1) & (n > 0) & (n < Inf) & (n == round (n))
-            & (p >= 0) & (p <= 1));
-  if (any (k))
-    inv(k) = Inf;
+  if (isa (x, "single") || isa (n, "single") || isa (p, "single"))
+    inv = zeros (size (x), "single");
+  else
+    inv = zeros (size (x));
   endif
 
+  k = (isnan (x) | (x < 0) | (x > 1) | isnan (n) | (n < 1) | (n == Inf)
+       | isnan (p) | (p < 0) | (p > 1));
+  inv(k) = NaN;
+
+  k = (x == 1) & (n > 0) & (n < Inf) & (p >= 0) & (p <= 1);
+  inv(k) = Inf;
+
   k = find ((x >= 0) & (x < 1) & (n > 0) & (n < Inf)
-            & (n == round (n)) & (p > 0) & (p <= 1));
-  if (any (k))
-    m = zeros (size (k));
-    x = x(k);
-    if (isscalar (n) && isscalar (p))
-      s = p ^ n * ones (size(k));
-      while (1)
-        l = find (s < x);
-        if (any (l))
-          m(l) = m(l) + 1;
-          s(l) = s(l) + nbinpdf (m(l), n, p);
-        else
-          break;
-        endif
-      endwhile
-    else
-      n = n(k);
-      p = p(k);
-      s = p .^ n;
-      while (1)
-        l = find (s < x);
-        if (any (l))
-          m(l) = m(l) + 1;
-          s(l) = s(l) + nbinpdf (m(l), n(l), p(l));
-        else
-          break;
-        endif
-      endwhile
-    endif
-    inv(k) = m;
+            & (p > 0) & (p <= 1));
+  m = zeros (size (k));
+  x = x(k);
+  if (isscalar (n) && isscalar (p))
+    s = p ^ n * ones (size (k));
+    while (1)
+      l = find (s < x);
+      if (any (l))
+        m(l) = m(l) + 1;
+        s(l) = s(l) + nbinpdf (m(l), n, p);
+      else
+        break;
+      endif
+    endwhile
+  else
+    n = n(k);
+    p = p(k);
+    s = p .^ n;
+    while (1)
+      l = find (s < x);
+      if (any (l))
+        m(l) = m(l) + 1;
+        s(l) = s(l) + nbinpdf (m(l), n(l), p(l));
+      else
+        break;
+      endif
+    endwhile
   endif
+  inv(k) = m;
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 3/4 1 2];
+%!assert(nbininv (x, ones(1,5), 0.5*ones(1,5)), [NaN 0 1 Inf NaN]);
+%!assert(nbininv (x, 1, 0.5*ones(1,5)), [NaN 0 1 Inf NaN]);
+%!assert(nbininv (x, ones(1,5), 0.5), [NaN 0 1 Inf NaN]);
+%!assert(nbininv (x, [1 0 NaN Inf 1], 0.5), [NaN NaN NaN NaN NaN]);
+%!assert(nbininv (x, [1 0 1.5 Inf 1], 0.5), [NaN NaN 2 NaN NaN]);
+%!assert(nbininv (x, 1, 0.5*[1 -Inf NaN Inf 1]), [NaN NaN NaN NaN NaN]);
+%!assert(nbininv ([x(1:2) NaN x(4:5)], 1, 0.5), [NaN 0 NaN Inf NaN]);
+
+%% Test class of input preserved
+%!assert(nbininv ([x, NaN], 1, 0.5), [NaN 0 1 Inf NaN NaN]);
+%!assert(nbininv (single([x, NaN]), 1, 0.5), single([NaN 0 1 Inf NaN NaN]));
+%!assert(nbininv ([x, NaN], single(1), 0.5), single([NaN 0 1 Inf NaN NaN]));
+%!assert(nbininv ([x, NaN], 1, single(0.5)), single([NaN 0 1 Inf NaN NaN]));
+
+%% Test input validation
+%!error nbininv ()
+%!error nbininv (1)
+%!error nbininv (1,2)
+%!error nbininv (1,2,3,4)
+%!error nbininv (ones(3),ones(2),ones(2))
+%!error nbininv (ones(2),ones(3),ones(2))
+%!error nbininv (ones(2),ones(2),ones(3))
+%!error nbininv (i, 2, 2)
+%!error nbininv (2, i, 2)
+%!error nbininv (2, 2, i)
+
--- a/scripts/statistics/distributions/nbinpdf.m
+++ b/scripts/statistics/distributions/nbinpdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -19,9 +20,12 @@
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} nbinpdf (@var{x}, @var{n}, @var{p})
 ## For each element of @var{x}, compute the probability density function
-## (PDF) at @var{x} of the Pascal (negative binomial) distribution with
+## (PDF) at @var{x} of the negative binomial distribution with
 ## parameters @var{n} and @var{p}.
 ##
+## When @var{n} is integer this is the Pascal distribution.  When
+## @var{n} is extended to real numbers this is the Polya distribution.
+## 
 ## The number of failures in a Bernoulli experiment with success
 ## probability @var{p} before the @var{n}-th success follows this
 ## distribution.
@@ -36,36 +40,63 @@
     print_usage ();
   endif
 
-  if (!isscalar(n) || !isscalar(p))
+  if (!isscalar (n) || !isscalar (p))
     [retval, x, n, p] = common_size (x, n, p);
     if (retval > 0)
-      error ("nbinpdf: X, N and P must be of common size or scalar");
+      error ("nbinpdf: X, N, and P must be of common size or scalars");
     endif
   endif
 
-  pdf = zeros (size (x));
+  if (iscomplex (x) || iscomplex (n) || iscomplex (p))
+    error ("nbinpdf: X, N, and P must not be complex");
+  endif
 
-  k = find (isnan (x) | (n < 1) | (n == Inf) | (n != round (n))
-            | (p < 0) | (p > 1));
-  if (any (k))
-    pdf(k) = NaN;
+  if (isa (x, "single") || isa (n, "single") || isa (p, "single"))
+    pdf = NaN (size (x), "single");
+  else
+    pdf = NaN (size (x));
   endif
 
-  ## Just for the fun of it ...
-  k = find ((x == Inf) & (n > 0) & (n < Inf) & (n == round (n))
-            & (p == 0));
-  if (any (k))
-    pdf(k) = 1;
-  endif
+  ok = (x < Inf) & (x == fix (x)) & (n > 0) & (n < Inf) & (p >= 0) & (p <= 1);
+
+  k = (x < 0) & ok;
+  pdf(k) = 0;
 
-  k = find ((x >= 0) & (x < Inf) & (x == round (x)) & (n > 0)
-            & (n < Inf) & (n == round (n)) & (p > 0) & (p <= 1));
-  if (any (k))
-    if (isscalar (n) && isscalar (p))
-      pdf(k) = bincoeff (-n, x(k)) .* (p ^ n) .* ((p - 1) .^ x(k));
-    else
-      pdf(k) = bincoeff (-n(k), x(k)) .* (p(k) .^ n(k)) .* ((p(k) - 1) .^ x(k));
-    endif
+  k = (x >= 0) & ok;
+  if (isscalar (n) && isscalar (p))
+    pdf(k) = bincoeff (-n, x(k)) .* (p ^ n) .* ((p - 1) .^ x(k));
+  else
+    pdf(k) = bincoeff (-n(k), x(k)) .* (p(k) .^ n(k)) .* ((p(k) - 1) .^ x(k));
   endif
+  
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 1 2 Inf];
+%! y = [0 1/2 1/4 1/8 NaN];
+%!assert(nbinpdf (x, ones(1,5), 0.5*ones(1,5)), y);
+%!assert(nbinpdf (x, 1, 0.5*ones(1,5)), y);
+%!assert(nbinpdf (x, ones(1,5), 0.5), y);
+%!assert(nbinpdf (x, [0 1 NaN 1.5 Inf], 0.5), [NaN 1/2 NaN 1.875*0.5^1.5/4 NaN], eps);
+%!assert(nbinpdf (x, 1, 0.5*[-1 NaN 4 1 1]), [NaN NaN NaN y(4:5)]);
+%!assert(nbinpdf ([x, NaN], 1, 0.5), [y, NaN]);
+
+%% Test class of input preserved
+%!assert(nbinpdf (single([x, NaN]), 1, 0.5), single([y, NaN]));
+%!assert(nbinpdf ([x, NaN], single(1), 0.5), single([y, NaN]));
+%!assert(nbinpdf ([x, NaN], 1, single(0.5)), single([y, NaN]));
+
+%% Test input validation
+%!error nbinpdf ()
+%!error nbinpdf (1)
+%!error nbinpdf (1,2)
+%!error nbinpdf (1,2,3,4)
+%!error nbinpdf (ones(3),ones(2),ones(2))
+%!error nbinpdf (ones(2),ones(3),ones(2))
+%!error nbinpdf (ones(2),ones(2),ones(3))
+%!error nbinpdf (i, 2, 2)
+%!error nbinpdf (2, i, 2)
+%!error nbinpdf (2, 2, i)
+
--- a/scripts/statistics/distributions/nbinrnd.m
+++ b/scripts/statistics/distributions/nbinrnd.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,85 +18,123 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} nbinrnd (@var{n}, @var{p}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} nbinrnd (@var{n}, @var{p}, @var{sz})
-## Return an @var{r} by @var{c} matrix of random samples from the Pascal
-## (negative binomial) distribution with parameters @var{n} and @var{p}.
-## Both @var{n} and @var{p} must be scalar or of size @var{r} by @var{c}.
+## @deftypefn  {Function File} {} nbinrnd (@var{n}, @var{p})
+## @deftypefnx {Function File} {} nbinrnd (@var{n}, @var{p}, @var{r})
+## @deftypefnx {Function File} {} nbinrnd (@var{n}, @var{p}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} nbinrnd (@var{n}, @var{p}, [@var{sz}])
+## Return a matrix of random samples from the negative binomial
+## distribution with parameters @var{n} and @var{p}.
 ##
-## If @var{r} and @var{c} are omitted, the size of the result matrix is
-## the common size of @var{n} and @var{p}.  Or if @var{sz} is a vector,
-## create a matrix of size @var{sz}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the common size of
+## @var{n} and @var{p}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the Pascal distribution
 
-function rnd = nbinrnd (n, p, r, c)
+function rnd = nbinrnd (n, p, varargin)
 
-  if (nargin > 1)
-    if (!isscalar(n) || !isscalar(p))
-      [retval, n, p] = common_size (n, p);
-      if (retval > 0)
-        error ("nbinrnd: N and P must be of common size or scalar");
-      endif
+  if (nargin < 2)
+    print_usage ();
+  endif
+
+  if (!isscalar (n) || !isscalar (p))
+    [retval, n, p] = common_size (n, p);
+    if (retval > 0)
+      error ("nbinrnd: N and P must be of common size or scalars");
     endif
   endif
 
-  if (nargin == 4)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("nbinrnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("nbinrnd: C must be a positive integer");
-    endif
-    sz = [r, c];
+  if (iscomplex (n) || iscomplex (p))
+    error ("nbinrnd: N and P must not be complex");
+  endif
 
-    if (any (size (n) != 1)
-        && ((length (size (n)) != length (sz)) || any (size (n) != sz)))
-      error ("nbinrnd: N and P must be scalar or of size [R, C]");
-    endif
-
+  if (nargin == 2)
+    sz = size (n);
   elseif (nargin == 3)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
     else
-      error ("nbinrnd: R must be a positive integer or vector");
+      error ("nbinrnd: dimension vector must be row vector of non-negative integers");
     endif
+  elseif (nargin > 3)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("nbinrnd: dimensions must be non-negative integers");
+    endif
+    sz = [varargin{:}];
+  endif
 
-    if (any (size (n) != 1)
-        && ((length (size (n)) != length (sz)) || any (size (n) != sz)))
-      error ("nbinrnd: N and P must be scalar or of size SZ");
-    endif
-  elseif (nargin == 2)
-    sz = size(n);
+  if (!isscalar (n) && !isequal (size (n), sz))
+    error ("nbinrnd: N and P must be scalar or of size SZ");
+  endif
+
+  if (isa (n, "single") || isa (p, "single"))
+    cls = "single";
   else
-    print_usage ();
+    cls = "double";
   endif
 
   if (isscalar (n) && isscalar (p))
-    if ((n < 1) || (n == Inf) || (n != round (n)) || (p <= 0) || (p > 1));
-      rnd = NaN (sz);
-    elseif ((n > 0) && (n < Inf) && (n == round (n))
-            && (p > 0) && (p <= 1))
+    if ((n > 0) && (n < Inf) && (p > 0) && (p <= 1))
       rnd = randp ((1 - p) ./ p .* randg (n, sz));
+      if (strcmp (cls, "single"))
+        rnd = single (rnd);
+      endif
+    elseif ((n > 0) && (n < Inf) && (p == 0))
+      rnd = zeros (sz, cls);
     else
-      rnd = zeros (sz);
+      rnd = NaN (sz, cls);
     endif
   else
-    rnd = zeros (sz);
+    rnd = NaN (sz, cls);
 
-    k = find ((n < 1) | (n == Inf) | (n != round (n)) | (p <= 0) | (p > 1));
-    if (any (k))
-      rnd(k) = NaN;
-    endif
+    k = (n > 0) & (n < Inf) & (p == 0);
+    rnd(k) = 0;
 
-    k = find ((n > 0) & (n < Inf) & (n == round (n)) & (p > 0) & (p <= 1));
-    if (any (k))
-      rnd(k) = randp ((1 - p(k)) ./ p(k) .* randg (n(k), size(k)));
-    endif
+    k = (n > 0) & (n < Inf) & (p > 0) & (p <= 1);
+    rnd(k) = randp ((1 - p(k)) ./ p(k) .* randg (n(k)));
   endif
 
 endfunction
+
+
+%!assert(size (nbinrnd (2, 1/2)), [1, 1]);
+%!assert(size (nbinrnd (2*ones(2,1), 1/2)), [2, 1]);
+%!assert(size (nbinrnd (2*ones(2,2), 1/2)), [2, 2]);
+%!assert(size (nbinrnd (2, 1/2*ones(2,1))), [2, 1]);
+%!assert(size (nbinrnd (2, 1/2*ones(2,2))), [2, 2]);
+%!assert(size (nbinrnd (2, 1/2, 3)), [3, 3]);
+%!assert(size (nbinrnd (2, 1/2, [4 1])), [4, 1]);
+%!assert(size (nbinrnd (2, 1/2, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (nbinrnd (2, 1/2)), "double");
+%!assert(class (nbinrnd (single(2), 1/2)), "single");
+%!assert(class (nbinrnd (single([2 2]), 1/2)), "single");
+%!assert(class (nbinrnd (2, single(1/2))), "single");
+%!assert(class (nbinrnd (2, single([1/2 1/2]))), "single");
+
+%% Test input validation
+%!error nbinrnd ()
+%!error nbinrnd (1)
+%!error nbinrnd (ones(3),ones(2))
+%!error nbinrnd (ones(2),ones(3))
+%!error nbinrnd (i, 2)
+%!error nbinrnd (2, i)
+%!error nbinrnd (1,2, -1)
+%!error nbinrnd (1,2, ones(2))
+%!error nbinrnd (1, 2, [2 -1 2])
+%!error nbinrnd (1,2, 1, ones(2))
+%!error nbinrnd (1,2, 1, -1)
+%!error nbinrnd (ones(2,2), 2, 3)
+%!error nbinrnd (ones(2,2), 2, [3, 2])
+%!error nbinrnd (ones(2,2), 2, 2, 3)
+
--- a/scripts/statistics/distributions/normcdf.m
+++ b/scripts/statistics/distributions/normcdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,56 +18,82 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} normcdf (@var{x}, @var{m}, @var{s})
+## @deftypefn  {Function File} {} normcdf (@var{x})
+## @deftypefnx {Function File} {} normcdf (@var{x}, @var{mu}, @var{sigma})
 ## For each element of @var{x}, compute the cumulative distribution
 ## function (CDF) at @var{x} of the normal distribution with mean
-## @var{m} and standard deviation @var{s}.
+## @var{mu} and standard deviation @var{sigma}.
 ##
-## Default values are @var{m} = 0, @var{s} = 1.
+## Default values are @var{mu} = 0, @var{sigma} = 1.
 ## @end deftypefn
 
 ## Author: TT <Teresa.Twaroch@ci.tuwien.ac.at>
 ## Description: CDF of the normal distribution
 
-function cdf = normcdf (x, m, s)
+function cdf = normcdf (x, mu = 0, sigma = 1)
 
-  if (! ((nargin == 1) || (nargin == 3)))
+  if (nargin != 1 && nargin != 3)
     print_usage ();
   endif
 
-  if (nargin == 1)
-    m = 0;
-    s = 1;
-  endif
-
-  if (!isscalar (m) || !isscalar (s))
-    [retval, x, m, s] = common_size (x, m, s);
+  if (!isscalar (mu) || !isscalar (sigma))
+    [retval, x, mu, sigma] = common_size (x, mu, sigma);
     if (retval > 0)
-      error ("normcdf: X, M and S must be of common size or scalar");
+      error ("normcdf: X, MU, and SIGMA must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  cdf = zeros (sz);
+  if (iscomplex (x) || iscomplex (mu) || iscomplex (sigma))
+    error ("normcdf: X, MU, and SIGMA must not be complex");
+  endif
 
-  if (isscalar (m) && isscalar(s))
-    if (find (isinf (m) | isnan (m) | !(s > 0) | !(s < Inf)))
-      cdf = NaN (sz);
+  if (isa (x, "single") || isa (mu, "single") || isa (sigma, "single"));
+    cdf = zeros (size (x), "single");
+  else
+    cdf = zeros (size (x));
+  endif
+
+  if (isscalar (mu) && isscalar (sigma))
+    if (!isinf (mu) && !isnan (mu) && (sigma > 0) && (sigma < Inf))
+      cdf = stdnormal_cdf ((x - mu) / sigma);
     else
-      cdf =  stdnormal_cdf ((x - m) ./ s);
+      cdf = NaN (size (x), class (cdf));
     endif
   else
-    k = find (isinf (m) | isnan (m) | !(s > 0) | !(s < Inf));
-    if (any (k))
-      cdf(k) = NaN;
-    endif
+    k = isinf (mu) | isnan (mu) | !(sigma > 0) | !(sigma < Inf);
+    cdf(k) = NaN;
 
-    k = find (!isinf (m) & !isnan (m) & (s > 0) & (s < Inf));
-    if (any (k))
-      cdf(k) = stdnormal_cdf ((x(k) - m(k)) ./ s(k));
-    endif
+    k = ! k;
+    cdf(k) = stdnormal_cdf ((x(k) - mu(k)) ./ sigma(k));
   endif
 
-  cdf((s == 0) & (x == m)) = 0.5;
+endfunction
+
+
+%!shared x,y
+%! x = [-Inf 1 2 Inf];
+%! y = [0, 0.5, 1/2*(1+erf(1/sqrt(2))), 1];
+%!assert(normcdf (x, ones(1,4), ones(1,4)), y);
+%!assert(normcdf (x, 1, ones(1,4)), y);
+%!assert(normcdf (x, ones(1,4), 1), y);
+%!assert(normcdf (x, [0 -Inf NaN Inf], 1), [y(1) NaN NaN NaN]);
+%!assert(normcdf (x, 1, [Inf NaN -1 0]), [NaN NaN NaN NaN]);
+%!assert(normcdf ([x(1:2) NaN x(4)], 1, 1), [y(1:2) NaN y(4)]);
 
-endfunction
+%% Test class of input preserved
+%!assert(normcdf ([x, NaN], 1, 1), [y, NaN]);
+%!assert(normcdf (single([x, NaN]), 1, 1), single([y, NaN]), eps("single"));
+%!assert(normcdf ([x, NaN], single(1), 1), single([y, NaN]), eps("single"));
+%!assert(normcdf ([x, NaN], 1, single(1)), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error normcdf ()
+%!error normcdf (1,2)
+%!error normcdf (1,2,3,4)
+%!error normcdf (ones(3),ones(2),ones(2))
+%!error normcdf (ones(2),ones(3),ones(2))
+%!error normcdf (ones(2),ones(2),ones(3))
+%!error normcdf (i, 2, 2)
+%!error normcdf (2, i, 2)
+%!error normcdf (2, 2, i)
+
--- a/scripts/statistics/distributions/norminv.m
+++ b/scripts/statistics/distributions/norminv.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,62 +18,76 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} norminv (@var{x}, @var{m}, @var{s})
+## @deftypefn  {Function File} {} norminv (@var{x})
+## @deftypefnx {Function File} {} norminv (@var{x}, @var{mu}, @var{sigma})
 ## For each element of @var{x}, compute the quantile (the inverse of the
-## CDF) at @var{x} of the normal distribution with mean @var{m} and
-## standard deviation @var{s}.
+## CDF) at @var{x} of the normal distribution with mean @var{mu} and
+## standard deviation @var{sigma}.
 ##
-## Default values are @var{m} = 0, @var{s} = 1.
+## Default values are @var{mu} = 0, @var{sigma} = 1.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Quantile function of the normal distribution
 
-function inv = norminv (x, m, s)
+function inv = norminv (x, mu = 0, sigma = 1)
 
   if (nargin != 1 && nargin != 3)
     print_usage ();
   endif
 
-  if (nargin == 1)
-    m = 0;
-    s = 1;
-  endif
-
-  if (!isscalar (m) || !isscalar (s))
-    [retval, x, m, s] = common_size (x, m, s);
+  if (!isscalar (mu) || !isscalar (sigma))
+    [retval, x, mu, sigma] = common_size (x, mu, sigma);
     if (retval > 0)
-      error ("norminv: X, M and S must be of common size or scalars");
+      error ("norminv: X, MU, and SIGMA must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  inv = zeros (sz);
+  if (iscomplex (x) || iscomplex (mu) || iscomplex (sigma))
+    error ("norminv: X, MU, and SIGMA must not be complex");
+  endif
 
-  if (isscalar (m) && isscalar (s))
-    if (find (isinf (m) | isnan (m) | !(s > 0) | !(s < Inf)))
-      inv = NaN (sz);
-    else
-      inv =  m + s .* stdnormal_inv (x);
+  if (isa (x, "single") || isa (mu, "single") || isa (sigma, "single"))
+    inv = NaN (size (x), "single");
+  else
+    inv = NaN (size (x));
+  endif
+
+  if (isscalar (mu) && isscalar (sigma))
+    if (!isinf (mu) && !isnan (mu) && (sigma > 0) && (sigma < Inf))
+      inv =  mu + sigma * stdnormal_inv (x);
     endif
   else
-    k = find (isinf (m) | isnan (m) | !(s > 0) | !(s < Inf));
-    if (any (k))
-      inv(k) = NaN;
-    endif
-
-    k = find (!isinf (m) & !isnan (m) & (s > 0) & (s < Inf));
-    if (any (k))
-      inv(k) = m(k) + s(k) .* stdnormal_inv (x(k));
-    endif
+    k = !isinf (mu) & !isnan (mu) & (sigma > 0) & (sigma < Inf);
+    inv(k) = mu(k) + sigma(k) .* stdnormal_inv (x(k));
   endif
 
-  k = find ((s == 0) & (x > 0) & (x < 1));
-  if (any (k))
-    inv(k) = m(k);
-  endif
+endfunction
+
+
+%!shared x
+%! x = [-1 0 0.5 1 2];
+%!assert(norminv (x, ones(1,5), ones(1,5)), [NaN -Inf 1 Inf NaN]);
+%!assert(norminv (x, 1, ones(1,5)), [NaN -Inf 1 Inf NaN]);
+%!assert(norminv (x, ones(1,5), 1), [NaN -Inf 1 Inf NaN]);
+%!assert(norminv (x, [1 -Inf NaN Inf 1], 1), [NaN NaN NaN NaN NaN]);
+%!assert(norminv (x, 1, [1 0 NaN Inf 1]), [NaN NaN NaN NaN NaN]);
+%!assert(norminv ([x(1:2) NaN x(4:5)], 1, 1), [NaN -Inf NaN Inf NaN]);
 
-  inv((s == 0) & (x == 0)) = -Inf;
-  inv((s == 0) & (x == 1)) = Inf;
+%% Test class of input preserved
+%!assert(norminv ([x, NaN], 1, 1), [NaN -Inf 1 Inf NaN NaN]);
+%!assert(norminv (single([x, NaN]), 1, 1), single([NaN -Inf 1 Inf NaN NaN]));
+%!assert(norminv ([x, NaN], single(1), 1), single([NaN -Inf 1 Inf NaN NaN]));
+%!assert(norminv ([x, NaN], 1, single(1)), single([NaN -Inf 1 Inf NaN NaN]));
 
-endfunction
+%% Test input validation
+%!error norminv ()
+%!error norminv (1,2)
+%!error norminv (1,2,3,4)
+%!error norminv (ones(3),ones(2),ones(2))
+%!error norminv (ones(2),ones(3),ones(2))
+%!error norminv (ones(2),ones(2),ones(3))
+%!error norminv (i, 2, 2)
+%!error norminv (2, i, 2)
+%!error norminv (2, 2, i)
+
--- a/scripts/statistics/distributions/normpdf.m
+++ b/scripts/statistics/distributions/normpdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,57 +18,81 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} normpdf (@var{x}, @var{m}, @var{s})
+## @deftypefn  {Function File} {} normpdf (@var{x})
+## @deftypefnx {Function File} {} normpdf (@var{x}, @var{mu}, @var{sigma})
 ## For each element of @var{x}, compute the probability density function
-## (PDF) at @var{x} of the normal distribution with mean @var{m} and
-## standard deviation @var{s}.
+## (PDF) at @var{x} of the normal distribution with mean @var{mu} and
+## standard deviation @var{sigma}.
 ##
-## Default values are @var{m} = 0, @var{s} = 1.
+## Default values are @var{mu} = 0, @var{sigma} = 1.
 ## @end deftypefn
 
 ## Author: TT <Teresa.Twaroch@ci.tuwien.ac.at>
 ## Description: PDF of the normal distribution
 
-function pdf = normpdf (x, m, s)
+function pdf = normpdf (x, mu = 0, sigma = 1)
 
   if (nargin != 1 && nargin != 3)
     print_usage ();
   endif
 
-  if (nargin == 1)
-    m = 0;
-    s = 1;
-  endif
-
-  if (!isscalar (m) || !isscalar (s))
-    [retval, x, m, s] = common_size (x, m, s);
+  if (!isscalar (mu) || !isscalar (sigma))
+    [retval, x, mu, sigma] = common_size (x, mu, sigma);
     if (retval > 0)
-      error ("normpdf: X, M and S must be of common size or scalars");
+      error ("normpdf: X, MU, and SIGMA must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  pdf = zeros (sz);
+  if (iscomplex (x) || iscomplex (mu) || iscomplex (sigma))
+    error ("normpdf: X, MU, and SIGMA must not be complex");
+  endif
 
-  if (isscalar (m) && isscalar (s))
-    if (find (isinf (m) | isnan (m) | !(s > 0) | !(s < Inf)))
-      pdf = NaN (sz);
+  if (isa (x, "single") || isa (mu, "single") || isa (sigma, "single"))
+    pdf = zeros (size (x), "single");
+  else
+    pdf = zeros (size (x));
+  endif
+
+  if (isscalar (mu) && isscalar (sigma))
+    if (!isinf (mu) && !isnan (mu) && (sigma > 0) && (sigma < Inf))
+      pdf = stdnormal_pdf ((x - mu) / sigma) / sigma;
     else
-      pdf = stdnormal_pdf ((x - m) ./ s) ./ s;
+      pdf = NaN (size (x), class (pdf));
     endif
   else
-    k = find (isinf (m) | isnan (m) | !(s > 0) | !(s < Inf));
-    if (any (k))
-      pdf(k) = NaN;
-    endif
+    k = isinf (mu) | !(sigma > 0) | !(sigma < Inf);
+    pdf(k) = NaN;
 
-    k = find (!isinf (m) & !isnan (m) & (s > 0) & (s < Inf));
-    if (any (k))
-      pdf(k) = stdnormal_pdf ((x(k) - m(k)) ./ s(k)) ./ s(k);
-    endif
+    k = !isinf (mu) & (sigma > 0) & (sigma < Inf);
+    pdf(k) = stdnormal_pdf ((x(k) - mu(k)) ./ sigma(k)) ./ sigma(k);
   endif
 
-  pdf((s == 0) & (x == m)) = Inf;
-  pdf((s == 0) & ((x < m) | (x > m))) = 0;
+endfunction
+
+
+%!shared x,y
+%! x = [-Inf 1 2 Inf];
+%! y = 1/sqrt(2*pi)*exp (-(x-1).^2/2);
+%!assert(normpdf (x, ones(1,4), ones(1,4)), y);
+%!assert(normpdf (x, 1, ones(1,4)), y);
+%!assert(normpdf (x, ones(1,4), 1), y);
+%!assert(normpdf (x, [0 -Inf NaN Inf], 1), [y(1) NaN NaN NaN]);
+%!assert(normpdf (x, 1, [Inf NaN -1 0]), [NaN NaN NaN NaN]);
+%!assert(normpdf ([x, NaN], 1, 1), [y, NaN]);
 
-endfunction
+%% Test class of input preserved
+%!assert(normpdf (single([x, NaN]), 1, 1), single([y, NaN]), eps("single"));
+%!assert(normpdf ([x, NaN], single(1), 1), single([y, NaN]), eps("single"));
+%!assert(normpdf ([x, NaN], 1, single(1)), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error normpdf ()
+%!error normpdf (1,2)
+%!error normpdf (1,2,3,4)
+%!error normpdf (ones(3),ones(2),ones(2))
+%!error normpdf (ones(2),ones(3),ones(2))
+%!error normpdf (ones(2),ones(2),ones(3))
+%!error normpdf (i, 2, 2)
+%!error normpdf (2, i, 2)
+%!error normpdf (2, 2, i)
+
--- a/scripts/statistics/distributions/normrnd.m
+++ b/scripts/statistics/distributions/normrnd.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,75 +18,114 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} normrnd (@var{m}, @var{s}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} normrnd (@var{m}, @var{s}, @var{sz})
-## Return an @var{r} by @var{c}  or @code{size (@var{sz})} matrix of
-## random samples from the normal distribution with parameters mean @var{m}
-## and standard deviation @var{s}.  Both @var{m} and @var{s} must be scalar
-## or of size @var{r} by @var{c}.
+## @deftypefn  {Function File} {} normrnd (@var{mu}, @var{sigma})
+## @deftypefnx {Function File} {} normrnd (@var{mu}, @var{sigma}, @var{r})
+## @deftypefnx {Function File} {} normrnd (@var{mu}, @var{sigma}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} normrnd (@var{mu}, @var{sigma}, [@var{sz}])
+## Return a matrix of random samples from the normal distribution with
+## parameters mean @var{mu} and standard deviation @var{sigma}.
 ##
-## If @var{r} and @var{c} are omitted, the size of the result matrix is
-## the common size of @var{m} and @var{s}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the common size of
+## @var{mu} and @var{sigma}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the normal distribution
 
-function rnd = normrnd (m, s, r, c)
+function rnd = normrnd (mu, sigma, varargin)
 
-  if (nargin > 1)
-    if (!isscalar (m) || !isscalar (s))
-      [retval, m, s] = common_size (m, s);
-      if (retval > 0)
-        error ("normrnd: M and S must be of common size or scalar");
-      endif
+  if (nargin < 2)
+    print_usage ();
+  endif
+
+  if (!isscalar (mu) || !isscalar (sigma))
+    [retval, mu, sigma] = common_size (mu, sigma);
+    if (retval > 0)
+      error ("normrnd: mu and sigma must be of common size or scalars");
     endif
   endif
 
-  if (nargin == 4)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("normrnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("normrnd: C must be a positive integer");
-    endif
-    sz = [r, c];
+  if (iscomplex (mu) || iscomplex (sigma))
+    error ("normrnd: MU and SIGMA must not be complex");
+  endif
 
-    if (any (size (m) != 1)
-        && (length (size (m)) != length (sz) || any (size (m) != sz)))
-      error ("normrnd: M and S must be scalar or of size [R, C]");
-    endif
+  if (nargin == 2)
+    sz = size (mu);
   elseif (nargin == 3)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
     else
-      error ("normrnd: R must be a positive integer or vector");
+      error ("normrnd: dimension vector must be row vector of non-negative integers");
     endif
-
-    if (any (size (m) != 1)
-        && (length (size (m)) != length (sz) || any (size (m) != sz)))
-      error ("normrnd: M and S must be scalar or of size SZ");
+  elseif (nargin > 3)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("normrnd: dimensions must be non-negative integers");
     endif
-  elseif (nargin == 2)
-    sz = size(m);
-  else
-    print_usage ();
+    sz = [varargin{:}];
   endif
 
-  if (isscalar (m) && isscalar (s))
-    if (find (isnan (m) | isinf (m) | !(s > 0) | !(s < Inf)))
-      rnd = NaN (sz);
+  if (!isscalar (mu) && !isequal (size (mu), sz))
+    error ("normrnd: mu and sigma must be scalar or of size SZ");
+  endif
+
+  if (isa (mu, "single") || isa (sigma, "single"))
+    cls = "single";
+  else
+    cls = "double";
+  endif
+
+  if (isscalar (mu) && isscalar (sigma))
+    if (!isnan (mu) && !isinf (mu) && (sigma > 0) && (sigma < Inf))
+      rnd =  mu + sigma * randn (sz);
     else
-      rnd =  m + s .* randn (sz);
+      rnd = NaN (sz, cls);
     endif
   else
-    rnd = m + s .* randn (sz);
-    k = find (isnan (m) | isinf (m) | !(s > 0) | !(s < Inf));
-    if (any (k))
-      rnd(k) = NaN;
-    endif
+    rnd = mu + sigma .* randn (sz);
+    k = isnan (mu) | isinf (mu) | !(sigma > 0) | !(sigma < Inf);
+    rnd(k) = NaN;
   endif
 
 endfunction
+
+
+%!assert(size (normrnd (1,2)), [1, 1]);
+%!assert(size (normrnd (ones(2,1), 2)), [2, 1]);
+%!assert(size (normrnd (ones(2,2), 2)), [2, 2]);
+%!assert(size (normrnd (1, 2*ones(2,1))), [2, 1]);
+%!assert(size (normrnd (1, 2*ones(2,2))), [2, 2]);
+%!assert(size (normrnd (1, 2, 3)), [3, 3]);
+%!assert(size (normrnd (1, 2, [4 1])), [4, 1]);
+%!assert(size (normrnd (1, 2, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (normrnd (1, 2)), "double");
+%!assert(class (normrnd (single(1), 2)), "single");
+%!assert(class (normrnd (single([1 1]), 2)), "single");
+%!assert(class (normrnd (1, single(2))), "single");
+%!assert(class (normrnd (1, single([2 2]))), "single");
+
+%% Test input validation
+%!error normrnd ()
+%!error normrnd (1)
+%!error normrnd (ones(3),ones(2))
+%!error normrnd (ones(2),ones(3))
+%!error normrnd (i, 2)
+%!error normrnd (2, i)
+%!error normrnd (1,2, -1)
+%!error normrnd (1,2, ones(2))
+%!error normrnd (1, 2, [2 -1 2])
+%!error normrnd (1,2, 1, ones(2))
+%!error normrnd (1,2, 1, -1)
+%!error normrnd (ones(2,2), 2, 3)
+%!error normrnd (ones(2,2), 2, [3, 2])
+%!error normrnd (ones(2,2), 2, 2, 3)
+
--- a/scripts/statistics/distributions/poisscdf.m
+++ b/scripts/statistics/distributions/poisscdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -35,29 +36,55 @@
   if (!isscalar (lambda))
     [retval, x, lambda] = common_size (x, lambda);
     if (retval > 0)
-      error ("poisscdf: X and LAMBDA must be of common size or scalar");
+      error ("poisscdf: X and LAMBDA must be of common size or scalars");
     endif
   endif
 
-  cdf = zeros (size (x));
+  if (iscomplex (x) || iscomplex (lambda))
+    error ("poisscdf: X and LAMBDA must not be complex");
+  endif
 
-  k = find (isnan (x) | !(lambda > 0));
-  if (any (k))
-    cdf(k) = NaN;
+  if (isa (x, "single") || isa (lambda, "single"))
+    cdf = zeros (size (x), "single");
+  else
+    cdf = zeros (size (x));
   endif
 
-  k = find ((x == Inf) & (lambda > 0));
-  if (any (k))
-    cdf(k) = 1;
-  endif
+  k = isnan (x) | !(lambda > 0);
+  cdf(k) = NaN;
+
+  k = (x == Inf) & (lambda > 0);
+  cdf(k) = 1;
 
-  k = find ((x >= 0) & (x < Inf) & (lambda > 0));
-  if (any (k))
-    if (isscalar (lambda))
-      cdf(k) = 1 - gammainc (lambda, floor (x(k)) + 1);
-    else
-      cdf(k) = 1 - gammainc (lambda(k), floor (x(k)) + 1);
-    endif
+  k = (x >= 0) & (x < Inf) & (lambda > 0);
+  if (isscalar (lambda))
+    cdf(k) = 1 - gammainc (lambda, floor (x(k)) + 1);
+  else
+    cdf(k) = 1 - gammainc (lambda(k), floor (x(k)) + 1);
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 1 2 Inf];
+%! y = [0, gammainc(1, (x(2:4) +1), 'upper'), 1];
+%!assert(poisscdf (x, ones(1,5)), y);
+%!assert(poisscdf (x, 1), y);
+%!assert(poisscdf (x, [1 0 NaN 1 1]), [y(1) NaN NaN y(4:5)]);
+%!assert(poisscdf ([x(1:2) NaN Inf x(5)], 1), [y(1:2) NaN 1 y(5)]);
+
+%% Test class of input preserved
+%!assert(poisscdf ([x, NaN], 1), [y, NaN]);
+%!assert(poisscdf (single([x, NaN]), 1), single([y, NaN]), eps("single"));
+%!assert(poisscdf ([x, NaN], single(1)), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error poisscdf ()
+%!error poisscdf (1)
+%!error poisscdf (1,2,3)
+%!error poisscdf (ones(3),ones(2))
+%!error poisscdf (ones(2),ones(3))
+%!error poisscdf (i, 2)
+%!error poisscdf (2, i)
+
--- a/scripts/statistics/distributions/poissinv.m
+++ b/scripts/statistics/distributions/poissinv.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,7 +19,7 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} poissinv (@var{x}, @var{lambda})
-## For each component of @var{x}, compute the quantile (the inverse of
+## For each element of @var{x}, compute the quantile (the inverse of
 ## the CDF) at @var{x} of the Poisson distribution with parameter
 ## @var{lambda}.
 ## @end deftypefn
@@ -35,42 +36,68 @@
   if (!isscalar (lambda))
     [retval, x, lambda] = common_size (x, lambda);
     if (retval > 0)
-      error ("poissinv: X and LAMBDA must be of common size or scalar");
+      error ("poissinv: X and LAMBDA must be of common size or scalars");
     endif
   endif
 
-  inv = zeros (size (x));
-
-  k = find ((x < 0) | (x > 1) | isnan (x) | !(lambda > 0));
-  if (any (k))
-    inv(k) = NaN;
+  if (iscomplex (x) || iscomplex (lambda))
+    error ("poissinv: X and LAMBDA must not be complex");
   endif
 
-  k = find ((x == 1) & (lambda > 0));
-  if (any (k))
-    inv(k) = Inf;
+  if (isa (x, "single") || isa (lambda, "single"))
+    inv = zeros (size (x), "single");
+  else
+    inv = zeros (size (x));
   endif
 
+  k = (x < 0) | (x > 1) | isnan (x) | !(lambda > 0);
+  inv(k) = NaN;
+
+  k = (x == 1) & (lambda > 0);
+  inv(k) = Inf;
+
   k = find ((x > 0) & (x < 1) & (lambda > 0));
-  if (any (k))
-    if (isscalar (lambda))
-      cdf = exp (-lambda) * ones (size (k));
+  if (isscalar (lambda))
+    cdf = exp (-lambda) * ones (size (k));
+  else
+    cdf = exp (-lambda(k));
+  endif
+  
+  while (1)
+    m = find (cdf < x(k));
+    if (any (m))
+      inv(k(m)) += 1;
+      if (isscalar (lambda))
+        cdf(m) = cdf(m) + poisspdf (inv(k(m)), lambda);
+      else
+        cdf(m) = cdf(m) + poisspdf (inv(k(m)), lambda(k(m)));
+      endif
     else
-      cdf = exp (-lambda(k));
+      break;
     endif
-    while (1)
-      m = find (cdf < x(k));
-      if (any (m))
-        inv(k(m)) = inv(k(m)) + 1;
-        if (isscalar (lambda))
-          cdf(m) = cdf(m) + poisspdf (inv(k(m)), lambda);
-        else
-          cdf(m) = cdf(m) + poisspdf (inv(k(m)), lambda(k(m)));
-        endif
-      else
-        break;
-      endif
-    endwhile
-  endif
+  endwhile
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.5 1 2];
+%!assert(poissinv (x, ones(1,5)), [NaN 0 1 Inf NaN]);
+%!assert(poissinv (x, 1), [NaN 0 1 Inf NaN]);
+%!assert(poissinv (x, [1 0 NaN 1 1]), [NaN NaN NaN Inf NaN]);
+%!assert(poissinv ([x(1:2) NaN x(4:5)], 1), [NaN 0 NaN Inf NaN]);
+
+%% Test class of input preserved
+%!assert(poissinv ([x, NaN], 1), [NaN 0 1 Inf NaN NaN]);
+%!assert(poissinv (single([x, NaN]), 1), single([NaN 0 1 Inf NaN NaN]));
+%!assert(poissinv ([x, NaN], single(1)), single([NaN 0 1 Inf NaN NaN]));
+
+%% Test input validation
+%!error poissinv ()
+%!error poissinv (1)
+%!error poissinv (1,2,3)
+%!error poissinv (ones(3),ones(2))
+%!error poissinv (ones(2),ones(3))
+%!error poissinv (i, 2)
+%!error poissinv (2, i)
+
--- a/scripts/statistics/distributions/poisspdf.m
+++ b/scripts/statistics/distributions/poisspdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -34,24 +35,51 @@
   if (!isscalar (lambda))
     [retval, x, lambda] = common_size (x, lambda);
     if (retval > 0)
-      error ("poisspdf: X and LAMBDA must be of common size or scalar");
+      error ("poisspdf: X and LAMBDA must be of common size or scalars");
     endif
   endif
 
-  pdf = zeros (size (x));
-
-  k = find (!(lambda > 0) | isnan (x));
-  if (any (k))
-    pdf(k) = NaN;
+  if (iscomplex (x) || iscomplex (lambda))
+    error ("poisspdf: X and LAMBDA must not be complex");
   endif
 
-  k = find ((x >= 0) & (x < Inf) & (x == round (x)) & (lambda > 0));
-  if (any (k))
-    if (isscalar (lambda))
-      pdf(k) = exp (x(k) .* log (lambda) - lambda - gammaln (x(k) + 1));
-    else
-      pdf(k) = exp (x(k) .* log (lambda(k)) - lambda(k) - gammaln (x(k) + 1));
-    endif
+  if (isa (x, "single") || isa (lambda, "single"))
+    pdf = zeros (size (x), "single");
+  else
+    pdf = zeros (size (x));
+  endif
+
+  k = isnan (x) | !(lambda > 0);
+  pdf(k) = NaN;
+
+  k = (x >= 0) & (x < Inf) & (x == fix (x)) & (lambda > 0);
+  if (isscalar (lambda))
+    pdf(k) = exp (x(k) * log (lambda) - lambda - gammaln (x(k) + 1));
+  else
+    pdf(k) = exp (x(k) .* log (lambda(k)) - lambda(k) - gammaln (x(k) + 1));
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 1 2 Inf];
+%! y = [0, exp(-1)*[1 1 0.5], 0];
+%!assert(poisspdf (x, ones(1,5)), y, eps);
+%!assert(poisspdf (x, 1), y, eps);
+%!assert(poisspdf (x, [1 0 NaN 1 1]), [y(1) NaN NaN y(4:5)], eps);
+%!assert(poisspdf ([x, NaN], 1), [y, NaN], eps);
+
+%% Test class of input preserved
+%!assert(poisspdf (single([x, NaN]), 1), single([y, NaN]), eps("single"));
+%!assert(poisspdf ([x, NaN], single(1)), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error poisspdf ()
+%!error poisspdf (1)
+%!error poisspdf (1,2,3)
+%!error poisspdf (ones(3),ones(2))
+%!error poisspdf (ones(2),ones(3))
+%!error poisspdf (i, 2)
+%!error poisspdf (2, i)
+
--- a/scripts/statistics/distributions/poissrnd.m
+++ b/scripts/statistics/distributions/poissrnd.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,73 +18,103 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} poissrnd (@var{lambda}, @var{r}, @var{c})
-## Return an @var{r} by @var{c} matrix of random samples from the
-## Poisson distribution with parameter @var{lambda}, which must be a
-## scalar or of size @var{r} by @var{c}.
+## @deftypefn  {Function File} {} poissrnd (@var{lambda})
+## @deftypefnx {Function File} {} poissrnd (@var{lambda}, @var{r})
+## @deftypefnx {Function File} {} poissrnd (@var{lambda}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} poissrnd (@var{lambda}, [@var{sz}])
+## Return a matrix of random samples from the Poisson distribution with
+## parameter @var{lambda}.
 ##
-## If @var{r} and @var{c} are omitted, the size of the result matrix is
-## the size of @var{lambda}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the size of
+## @var{lambda}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the Poisson distribution
 
-function rnd = poissrnd (lambda, r, c)
-
-  if (nargin == 3)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("poissrnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("poissrnd: C must be a positive integer");
-    endif
-    sz = [r, c];
+function rnd = poissrnd (lambda, varargin)
 
-    if (any (size (lambda) != 1)
-        && ((length (size (lambda)) != length (sz)) || any (size (lambda) != sz)))
-      error ("poissrnd: LAMBDA must be scalar or of size [R, C]");
-    endif
-  elseif (nargin == 2)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
-    else
-      error ("poissrnd: R must be a positive integer or vector");
-    endif
-
-    if (any (size (lambda) != 1)
-        && ((length (size (lambda)) != length (sz)) || any (size (lambda) != sz)))
-      error ("poissrnd: LAMBDA must be scalar or of size sz");
-    endif
-  elseif (nargin == 1)
-    sz = size (lambda);
-  else
+  if (nargin < 1)
     print_usage ();
   endif
 
-  if (isscalar (lambda))
+  if (nargin == 1)
+    sz = size (lambda);
+  elseif (nargin == 2)
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
+    else
+      error ("poissrnd: dimension vector must be row vector of non-negative integers");
+    endif
+  elseif (nargin > 2)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("poissrnd: dimensions must be non-negative integers");
+    endif
+    sz = [varargin{:}];
+  endif
 
-    if (!(lambda >= 0) || !(lambda < Inf))
-      rnd = NaN (sz);
-    elseif (lambda > 0 && lambda < Inf)
-      rnd = randp(lambda, sz);
+  if (!isscalar (lambda) && !isequal (size (lambda), sz))
+    error ("poissrnd: LAMBDA must be scalar or of size SZ");
+  endif
+
+  if (iscomplex (lambda))
+    error ("poissrnd: LAMBDA must not be complex");
+  endif
+
+  if (isa (lambda, "single"))
+    cls = "single";
+  else
+    cls = "double";
+  endif
+
+  if (isscalar (lambda))
+    if (lambda > 0 && lambda < Inf)
+      rnd = randp (lambda, sz);
+      if (strcmp (cls, "single"))
+        rnd = single (rnd);
+      endif
     else
-      rnd = zeros (sz);
+      rnd = NaN (sz, cls);
     endif
   else
-    rnd = zeros (sz);
+    rnd = NaN (sz, cls);
 
-    k = find (!(lambda >= 0) | !(lambda < Inf));
-    if (any (k))
-      rnd(k) = NaN;
-    endif
-
-    k = find ((lambda > 0) & (lambda < Inf));
-    if (any (k))
-      rnd(k) = randp(lambda(k), size(k));
-    endif
+    k = (lambda > 0) & (lambda < Inf);
+    rnd(k) = randp (lambda(k));
   endif
 
 endfunction
+
+
+%!assert(size (poissrnd (2)), [1, 1]);
+%!assert(size (poissrnd (ones(2,1))), [2, 1]);
+%!assert(size (poissrnd (ones(2,2))), [2, 2]);
+%!assert(size (poissrnd (1, 3)), [3, 3]);
+%!assert(size (poissrnd (1, [4 1])), [4, 1]);
+%!assert(size (poissrnd (1, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (poissrnd (2)), "double");
+%!assert(class (poissrnd (single(2))), "single");
+%!assert(class (poissrnd (single([2 2]))), "single");
+
+%% Test input validation
+%!error poissrnd ()
+%!error poissrnd (1, -1)
+%!error poissrnd (1, ones(2))
+%!error poissrnd (1, 2, ones(2))
+%!error poissrnd (i)
+%!error poissrnd (1, 2, -1)
+%!error poissrnd (1, [2 -1 2])
+%!error poissrnd (ones(2,2), 3)
+%!error poissrnd (ones(2,2), [3, 2])
+%!error poissrnd (ones(2,2), 2, 3)
+
--- a/scripts/statistics/distributions/stdnormal_cdf.m
+++ b/scripts/statistics/distributions/stdnormal_cdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,8 +19,9 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} stdnormal_cdf (@var{x})
-## For each component of @var{x}, compute the CDF of the standard normal
-## distribution at @var{x}.
+## For each element of @var{x}, compute the cumulative distribution
+## function (CDF) at @var{x} of the standard normal distribution
+## (mean = 0, standard deviation = 1).
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -31,9 +33,8 @@
     print_usage ();
   endif
 
-  sz = size (x);
-  if (numel(x) == 0)
-    error ("stdnormal_cdf: X must not be empty");
+  if (iscomplex (x))
+    error ("stdnormal_cdf: X must not be complex");
   endif
 
   cdf = erfc (x / (-sqrt(2))) / 2;
@@ -41,5 +42,16 @@
 endfunction
 
 
+%!shared x,y
+%! x = [-Inf 0 1 Inf];
+%! y = [0, 0.5, 1/2*(1+erf(1/sqrt(2))), 1];
+%!assert(stdnormal_cdf ([x, NaN]), [y, NaN]);
 
+%% Test class of input preserved
+%!assert(stdnormal_cdf (single([x, NaN])), single([y, NaN]), eps("single"));
 
+%% Test input validation
+%!error stdnormal_cdf ()
+%!error stdnormal_cdf (1,2)
+%!error stdnormal_cdf (i)
+
--- a/scripts/statistics/distributions/stdnormal_inv.m
+++ b/scripts/statistics/distributions/stdnormal_inv.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,8 +19,9 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} stdnormal_inv (@var{x})
-## For each component of @var{x}, compute the quantile (the
-## inverse of the CDF) at @var{x} of the standard normal distribution.
+## For each element of @var{x}, compute the quantile (the
+## inverse of the CDF) at @var{x} of the standard normal distribution
+## (mean = 0, standard deviation = 1).
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
@@ -31,6 +33,25 @@
     print_usage ();
   endif
 
+  if (iscomplex (x))
+    error ("stdnormal_inv: X must not be complex");
+  endif
+
   inv = sqrt (2) * erfinv (2 * x - 1);
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.5 1 2];
+%!assert(stdnormal_inv (x), [NaN -Inf 0 Inf NaN]);
+
+%% Test class of input preserved
+%!assert(stdnormal_inv ([x, NaN]), [NaN -Inf 0 Inf NaN NaN]);
+%!assert(stdnormal_inv (single([x, NaN])), single([NaN -Inf 0 Inf NaN NaN]));
+
+%% Test input validation
+%!error stdnormal_inv ()
+%!error stdnormal_inv (1,2)
+%!error stdnormal_inv (i)
+
--- a/scripts/statistics/distributions/stdnormal_pdf.m
+++ b/scripts/statistics/distributions/stdnormal_pdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -19,7 +20,8 @@
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} stdnormal_pdf (@var{x})
 ## For each element of @var{x}, compute the probability density function
-## (PDF) of the standard normal distribution at @var{x}.
+## (PDF) at @var{x} of the standard normal distribution (mean = 0,
+## standard deviation = 1).
 ## @end deftypefn
 
 ## Author: TT <Teresa.Twaroch@ci.tuwien.ac.at>
@@ -31,17 +33,25 @@
     print_usage ();
   endif
 
-  sz = size(x);
-  pdf = zeros (sz);
-
-  k = find (isnan (x));
-  if (any (k))
-    pdf(k) = NaN;
+  if (iscomplex (x))
+    error ("stdnormal_pdf: X must not be complex");
   endif
 
-  k = find (!isinf (x));
-  if (any (k))
-    pdf (k) = (2 * pi)^(- 1/2) * exp (- x(k) .^ 2 / 2);
-  endif
+  pdf = (2 * pi)^(- 1/2) * exp (- x .^ 2 / 2);
 
 endfunction
+
+
+%!shared x,y
+%! x = [-Inf 0 1 Inf];
+%! y = 1/sqrt(2*pi)*exp (-x.^2/2);
+%!assert(stdnormal_pdf ([x, NaN]), [y, NaN], eps);
+
+%% Test class of input preserved
+%!assert(stdnormal_pdf (single([x, NaN])), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error stdnormal_pdf ()
+%!error stdnormal_pdf (1,2)
+%!error stdnormal_pdf (i)
+
--- a/scripts/statistics/distributions/stdnormal_rnd.m
+++ b/scripts/statistics/distributions/stdnormal_rnd.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,39 +18,57 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} stdnormal_rnd (@var{r}, @var{c})
-## @deftypefnx {Function File} {} stdnormal_rnd (@var{sz})
-## Return an @var{r} by @var{c} or @code{size (@var{sz})} matrix of
-## random numbers from the standard normal distribution.
+## @deftypefn  {Function File} {} stdnormal_rnd (@var{r})
+## @deftypefnx {Function File} {} stdnormal_rnd (@var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} stdnormal_rnd ([@var{sz}])
+## Return a matrix of random samples from the standard normal distribution
+## (mean = 0, standard deviation = 1).
+##
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the standard normal distribution
 
-function rnd = stdnormal_rnd (r, c)
+function rnd = stdnormal_rnd (varargin)
 
-  if (nargin != 1 && nargin != 2)
+  if (nargin < 1)
     print_usage ();
   endif
 
-  if (nargin == 2)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("stdnormal_rnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("stdnormal_rnd: C must be a positive integer");
+  if (nargin == 1)
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
+    else
+      error ("stdnormal_rnd: dimension vector must be row vector of non-negative integers");
     endif
-    sz = [r, c];
-  else
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
-    else
-      error ("stdnormal_rnd: R must be a positive integer or vector");
+  elseif (nargin > 1)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("stdnormal_rnd: dimensions must be non-negative integers");
     endif
+    sz = [varargin{:}];
   endif
 
   rnd = randn (sz);
 
 endfunction
+
+
+%!assert(size (stdnormal_rnd (3)), [3, 3]);
+%!assert(size (stdnormal_rnd ([4 1])), [4, 1]);
+%!assert(size (stdnormal_rnd (4,1)), [4, 1]);
+
+%% Test input validation
+%!error stdnormal_rnd ()
+%!error stdnormal_rnd (-1)
+%!error stdnormal_rnd (ones(2))
+%!error stdnormal_rnd ([2 -1 2])
+%!error stdnormal_rnd (1, ones(2))
+%!error stdnormal_rnd (1, -1)
+
--- a/scripts/statistics/distributions/tcdf.m
+++ b/scripts/statistics/distributions/tcdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -35,33 +36,59 @@
   if (!isscalar (n))
     [retval, x, n] = common_size (x, n);
     if (retval > 0)
-      error ("tcdf: X and N must be of common size or scalar");
+      error ("tcdf: X and N must be of common size or scalars");
     endif
   endif
 
-  cdf = zeros (size (x));
+  if (iscomplex (x) || iscomplex (n))
+    error ("tcdf: X and N must not be complex");
+  endif
 
-  k = find (isnan (x) | !(n > 0));
-  if (any (k))
-    cdf(k) = NaN;
+  if (isa (x, "single") || isa (n, "single"))
+    cdf = zeros (size (x), "single");
+  else
+    cdf = zeros (size (x));
   endif
 
-  k = find ((x == Inf) & (n > 0));
-  if (any (k))
-    cdf(k) = 1;
+  k = !isinf (x) & (n > 0);
+  if (isscalar (n))
+    cdf(k) = betainc (1 ./ (1 + x(k) .^ 2 / n), n/2, 1/2) / 2;
+  else
+    cdf(k) = betainc (1 ./ (1 + x(k) .^ 2 ./ n(k)), n(k)/2, 1/2) / 2;
+  endif
+  k &= (x > 0);
+  if (any (k(:)))
+    cdf(k) = 1 - cdf(k);
   endif
 
-  k = find ((x > -Inf) & (x < Inf) & (n > 0));
-  if (any (k))
-    if (isscalar (n))
-      cdf(k) = betainc (1 ./ (1 + x(k) .^ 2 ./ n), n / 2, 1 / 2) / 2;
-    else
-      cdf(k) = betainc (1 ./ (1 + x(k) .^ 2 ./ n(k)), n(k) / 2, 1 / 2) / 2;
-    endif
-    ind = find (x(k) > 0);
-    if (any (ind))
-      cdf(k(ind)) = 1 - cdf(k(ind));
-    endif
-  endif
+  k = isnan (x) | !(n > 0);
+  cdf(k) = NaN;
+
+  k = (x == Inf) & (n > 0);
+  cdf(k) = 1;
 
 endfunction
+
+
+%!shared x,y
+%! x = [-Inf 0 1 Inf];
+%! y = [0 1/2 3/4 1];
+%!assert(tcdf (x, ones(1,4)), y, eps);
+%!assert(tcdf (x, 1), y, eps);
+%!assert(tcdf (x, [0 1 NaN 1]), [NaN 1/2 NaN 1], eps);
+%!assert(tcdf ([x(1:2) NaN x(4)], 1), [y(1:2) NaN y(4)], eps);
+
+%% Test class of input preserved
+%!assert(tcdf ([x, NaN], 1), [y, NaN], eps);
+%!assert(tcdf (single([x, NaN]), 1), single([y, NaN]), eps("single"));
+%!assert(tcdf ([x, NaN], single(1)), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error tcdf ()
+%!error tcdf (1)
+%!error tcdf (1,2,3)
+%!error tcdf (ones(3),ones(2))
+%!error tcdf (ones(2),ones(3))
+%!error tcdf (i, 2)
+%!error tcdf (2, i)
+
--- a/scripts/statistics/distributions/tinv.m
+++ b/scripts/statistics/distributions/tinv.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -18,11 +19,10 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} tinv (@var{x}, @var{n})
-## For each probability value @var{x}, compute the inverse of the
-## cumulative distribution function (CDF) of the t (Student)
-## distribution with degrees of freedom @var{n}.  This function is
-## analogous to looking in a table for the t-value of a single-tailed
-## distribution.
+## For each element of @var{x}, compute the quantile (the inverse of
+## the CDF) at @var{x} of the t (Student) distribution with @var{n} 
+## degrees of freedom.  This function is analogous to looking in a table
+## for the t-value of a single-tailed distribution.
 ## @end deftypefn
 
 ## For very large n, the "correct" formula does not really work well,
@@ -41,44 +41,68 @@
   if (!isscalar (n))
     [retval, x, n] = common_size (x, n);
     if (retval > 0)
-      error ("tinv: X and N must be of common size or scalar");
+      error ("tinv: X and N must be of common size or scalars");
     endif
   endif
 
-  inv = zeros (size (x));
-
-  k = find ((x < 0) | (x > 1) | isnan (x) | !(n > 0));
-  if (any (k))
-    inv(k) = NaN;
+  if (iscomplex (x) || iscomplex (n))
+    error ("tinv: X and N must not be complex");
   endif
 
-  k = find ((x == 0) & (n > 0));
-  if (any (k))
-    inv(k) = -Inf;
-  endif
-
-  k = find ((x == 1) & (n > 0));
-  if (any (k))
-    inv(k) = Inf;
+  if (isa (x, "single") || isa (n, "single"))
+    inv = NaN (size (x), "single");
+  else
+    inv = NaN (size (x));
   endif
 
-  k = find ((x > 0) & (x < 1) & (n > 0) & (n < 10000));
-  if (any (k))
-    if (isscalar (n))
-      inv(k) = (sign (x(k) - 1/2)
-                .* sqrt (n .* (1 ./ betainv (2*min (x(k), 1 - x(k)),
-                                                 n/2, 1/2) - 1)));
-    else
+  k = (x == 0) & (n > 0);
+  inv(k) = -Inf;
+
+  k = (x == 1) & (n > 0);
+  inv(k) = Inf;
+
+  if (isscalar (n))
+    k = (x > 0) & (x < 1);
+    if ((n > 0) && (n < 10000))
       inv(k) = (sign (x(k) - 1/2)
-                .* sqrt (n(k) .* (1 ./ betainv (2*min (x(k), 1 - x(k)),
-                                                 n(k)/2, 1/2) - 1)));
+                .* sqrt (n * (1 ./ betainv (2*min (x(k), 1 - x(k)),
+                                            n/2, 1/2) - 1)));
+    elseif (n >= 10000)
+      ## For large n, use the quantiles of the standard normal
+      inv(k) = stdnormal_inv (x(k));
     endif
-  endif
+  else
+    k = (x > 0) & (x < 1) & (n > 0) & (n < 10000);
+    inv(k) = (sign (x(k) - 1/2)
+              .* sqrt (n(k) .* (1 ./ betainv (2*min (x(k), 1 - x(k)),
+                                              n(k)/2, 1/2) - 1)));
 
-  ## For large n, use the quantiles of the standard normal
-  k = find ((x > 0) & (x < 1) & (n >= 10000));
-  if (any (k))
+    ## For large n, use the quantiles of the standard normal
+    k = (x > 0) & (x < 1) & (n >= 10000);
     inv(k) = stdnormal_inv (x(k));
   endif
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.5 1 2];
+%!assert(tinv (x, ones(1,5)), [NaN -Inf 0 Inf NaN]);
+%!assert(tinv (x, 1), [NaN -Inf 0 Inf NaN], eps);
+%!assert(tinv (x, [1 0 NaN 1 1]), [NaN NaN NaN Inf NaN], eps);
+%!assert(tinv ([x(1:2) NaN x(4:5)], 1), [NaN -Inf NaN Inf NaN]);
+
+%% Test class of input preserved
+%!assert(tinv ([x, NaN], 1), [NaN -Inf 0 Inf NaN NaN], eps);
+%!assert(tinv (single([x, NaN]), 1), single([NaN -Inf 0 Inf NaN NaN]), eps("single"));
+%!assert(tinv ([x, NaN], single(1)), single([NaN -Inf 0 Inf NaN NaN]), eps("single"));
+
+%% Test input validation
+%!error tinv ()
+%!error tinv (1)
+%!error tinv (1,2,3)
+%!error tinv (ones(3),ones(2))
+%!error tinv (ones(2),ones(3))
+%!error tinv (i, 2)
+%!error tinv (2, i)
+
--- a/scripts/statistics/distributions/tpdf.m
+++ b/scripts/statistics/distributions/tpdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -35,26 +36,58 @@
   if (!isscalar (n))
     [retval, x, n] = common_size (x, n);
     if (retval > 0)
-      error ("tpdf: X and N must be of common size or scalar");
+      error ("tpdf: X and N must be of common size or scalars");
     endif
   endif
 
-  pdf = zeros (size (x));
+  if (iscomplex (x) || iscomplex (n))
+    error ("tpdf: X and N must not be complex");
+  endif
 
-  k = find (isnan (x) | !(n > 0) | !(n < Inf));
-  if (any (k))
-    pdf(k) = NaN;
+  if (isa (x, "single") || isa (n, "single"))
+    pdf = zeros (size (x), "single");
+  else
+    pdf = zeros (size (x));
   endif
 
-  k = find (!isinf (x) & !isnan (x) & (n > 0) & (n < Inf));
-  if (any (k))
-    if (isscalar (n))
-      pdf(k) = (exp (- (n + 1) .* log (1 + x(k) .^ 2 ./ n)/2)
-                / (sqrt (n) * beta (n/2, 1/2)));
-    else
-      pdf(k) = (exp (- (n(k) + 1) .* log (1 + x(k) .^ 2 ./ n(k))/2)
-                ./ (sqrt (n(k)) .* beta (n(k)/2, 1/2)));
-    endif
+  k = isnan (x) | !(n > 0) | !(n < Inf);
+  pdf(k) = NaN;
+
+  k = !isinf (x) & !isnan (x) & (n > 0) & (n < Inf);
+  if (isscalar (n))
+    pdf(k) = (exp (- (n + 1) * log (1 + x(k) .^ 2 / n)/2)
+              / (sqrt (n) * beta (n/2, 1/2)));
+  else
+    pdf(k) = (exp (- (n(k) + 1) .* log (1 + x(k) .^ 2 ./ n(k))/2)
+              ./ (sqrt (n(k)) .* beta (n(k)/2, 1/2)));
   endif
 
 endfunction
+
+
+%!test
+%! x = rand (10,1);
+%! y = 1./(pi * (1 + x.^2));
+%! assert(tpdf (x, 1), y, 5*eps);
+
+%!shared x,y
+%! x = [-Inf 0 0.5 1 Inf];
+%! y = 1./(pi * (1 + x.^2));
+%!assert(tpdf (x, ones(1,5)), y, eps);
+%!assert(tpdf (x, 1), y, eps);
+%!assert(tpdf (x, [0 NaN 1 1 1]), [NaN NaN y(3:5)], eps);
+
+%% Test class of input preserved
+%!assert(tpdf ([x, NaN], 1), [y, NaN]);
+%!assert(tpdf (single([x, NaN]), 1), single([y, NaN]), eps("single"));
+%!assert(tpdf ([x, NaN], single(1)), single([y, NaN]), eps("single"));
+
+%% Test input validation
+%!error tpdf ()
+%!error tpdf (1)
+%!error tpdf (1,2,3)
+%!error tpdf (ones(3),ones(2))
+%!error tpdf (ones(2),ones(3))
+%!error tpdf (i, 2)
+%!error tpdf (2, i)
+
--- a/scripts/statistics/distributions/trnd.m
+++ b/scripts/statistics/distributions/trnd.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,74 +18,100 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} trnd (@var{n}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} trnd (@var{n}, @var{sz})
-## Return an @var{r} by @var{c} matrix of random samples from the t
-## (Student) distribution with @var{n} degrees of freedom.  @var{n} must
-## be a scalar or of size @var{r} by @var{c}.  Or if @var{sz} is a
-## vector create a matrix of size @var{sz}.
+## @deftypefn  {Function File} {} trnd (@var{n})
+## @deftypefnx {Function File} {} trnd (@var{n}, @var{r})
+## @deftypefnx {Function File} {} trnd (@var{n}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} trnd (@var{n}, [@var{sz}])
+## Return a matrix of random samples from the t (Student) distribution with
+## @var{n} degrees of freedom.
 ##
-## If @var{r} and @var{c} are omitted, the size of the result matrix is
-## the size of @var{n}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the size of
+## @var{n}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the t distribution
 
-function rnd = trnd (n, r, c)
-
-  if (nargin == 3)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("trnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("trnd: C must be a positive integer");
-    endif
-    sz = [r, c];
+function rnd = trnd (n, varargin)
 
-    if (any (size (n) != 1)
-        && ((length (size (n)) != length (sz)) || any (size (n) != sz)))
-      error ("trnd: N must be scalar or of size SZ");
-    endif
-  elseif (nargin == 2)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
-    else
-      error ("trnd: R must be a positive integer or vector");
-    endif
-
-    if (any (size (n) != 1)
-        && ((length (size (n)) != length (sz)) || any (size (n) != sz)))
-      error ("trnd: N must be scalar or of size SZ");
-    endif
-  elseif (nargin == 1)
-    sz = size (n);
-  else
+  if (nargin < 1)
     print_usage ();
   endif
 
+  if (nargin == 1)
+    sz = size (n);
+  elseif (nargin == 2)
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
+    else
+      error ("trnd: dimension vector must be row vector of non-negative integers");
+    endif
+  elseif (nargin > 2)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("trnd: dimensions must be non-negative integers");
+    endif
+    sz = [varargin{:}];
+  endif
+
+  if (!isscalar (n) && !isequal (size (n), sz))
+    error ("trnd: N must be scalar or of size SZ");
+  endif
+
+  if (iscomplex (n))
+    error ("trnd: N must not be complex");
+  endif
+
+  if (isa (n, "single"))
+    cls = "single";
+  else
+    cls = "double";
+  endif
+
   if (isscalar (n))
-    if (!(n > 0) || !(n < Inf))
-      rnd = NaN (sz);
-    elseif ((n > 0) && (n < Inf))
-      rnd = randn(sz) ./ sqrt(2*randg(n/2,sz)./n);
+    if ((n > 0) && (n < Inf))
+      rnd = randn (sz) ./ sqrt (2*randg (n/2, sz) / n);
     else
-      rnd = zeros (size (n));
+      rnd = NaN (sz, cls);
     endif
   else
-    rnd = zeros (size (n));
+    rnd = NaN (sz, cls);
 
-    k = find (!(n > 0) | !(n < Inf));
-    if (any (k))
-      rnd(k) = NaN;
-    endif
-
-    k = find ((n > 0) & (n < Inf));
-    if (any (k))
-      rnd(k) = randn(size(k)) ./ sqrt(2*randg(n(k)/2,size(k))./n(k));
-    endif
+    k = (n > 0) & (n < Inf);
+    rnd(k) = randn (sum (k(:)), 1) ./ sqrt (2*randg (n(k)/2) ./ n(k))(:);
   endif
 
 endfunction
+
+
+%!assert(size (trnd (2)), [1, 1]);
+%!assert(size (trnd (ones(2,1))), [2, 1]);
+%!assert(size (trnd (ones(2,2))), [2, 2]);
+%!assert(size (trnd (1, 3)), [3, 3]);
+%!assert(size (trnd (1, [4 1])), [4, 1]);
+%!assert(size (trnd (1, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (trnd (1)), "double");
+%!assert(class (trnd (single(1))), "single");
+%!assert(class (trnd (single([1 1]))), "single");
+
+%% Test input validation
+%!error trnd ()
+%!error trnd (1, -1)
+%!error trnd (1, ones(2))
+%!error trnd (i)
+%!error trnd (1, [2 -1 2])
+%!error trnd (1, 2, ones(2))
+%!error trnd (1, 2, -1)
+%!error trnd (ones(2,2), 3)
+%!error trnd (ones(2,2), [3, 2])
+%!error trnd (ones(2,2), 2, 3)
+
--- a/scripts/statistics/distributions/unidcdf.m
+++ b/scripts/statistics/distributions/unidcdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 2007-2011 David Bateman
 ##
 ## This file is part of Octave.
@@ -17,26 +18,72 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} unidcdf (@var{x}, @var{v})
+## @deftypefn {Function File} {} unidcdf (@var{x}, @var{n})
 ## For each element of @var{x}, compute the cumulative distribution
-## function (CDF) at @var{x} of a discrete uniform distribution which
-## assumes the values in @var{v} with equal probability.
-## If @var{v} is a scalar then @code{1/@var{v}} is the probability of a
-## single element.
+## function (CDF) at @var{x} of a discrete uniform distribution which assumes
+## the integer values 1--@var{n} with equal probability.
 ## @end deftypefn
 
-function cdf = unidcdf (x, v)
+function cdf = unidcdf (x, n)
 
   if (nargin != 2)
     print_usage ();
   endif
 
-  if (isscalar(v))
-    v = [1:v].';
+  if (! isscalar (n))
+    [retval, x, n] = common_size (x, n);
+    if (retval > 0)
+      error ("unidcdf: X and N must be of common size or scalars");
+    endif
+  endif
+
+  if (iscomplex (x) || iscomplex (n))
+    error ("unidcdf: X and N must not be complex");
+  endif
+
+  if (isa (x, "single") || isa (n, "single"))
+    cdf = zeros (size (x), "single");
   else
-    v = v(:);
+    cdf = zeros (size (x));
+  endif
+
+  knan = isnan (x) | ! (n > 0 & n == fix (n));
+  if (any (knan(:)))
+    cdf(knan) = NaN;
   endif
 
-  cdf = discrete_cdf (x, v, ones(size(v)));
+  k = (x >= n) & !knan;  
+  cdf(k) = 1;
+
+  k = (x >= 1) & (x < n) & !knan;
+  if (isscalar (n))
+    cdf(k) = floor (x(k)) / n;
+  else
+    cdf(k) = floor (x(k)) ./ n(k);
+  endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [0 1 2.5 10 11];
+%! y = [0, 0.1 0.2 1.0 1.0];
+%!assert(unidcdf (x, 10*ones(1,5)), y);
+%!assert(unidcdf (x, 10), y);
+%!assert(unidcdf (x, 10*[0 1 NaN 1 1]), [NaN 0.1 NaN y(4:5)]);
+%!assert(unidcdf ([x(1:2) NaN Inf x(5)], 10), [y(1:2) NaN 1 y(5)]);
+
+%% Test class of input preserved
+%!assert(unidcdf ([x, NaN], 10), [y, NaN]);
+%!assert(unidcdf (single([x, NaN]), 10), single([y, NaN]));
+%!assert(unidcdf ([x, NaN], single(10)), single([y, NaN]));
+
+%% Test input validation
+%!error unidcdf ()
+%!error unidcdf (1)
+%!error unidcdf (1,2,3)
+%!error unidcdf (ones(3),ones(2))
+%!error unidcdf (ones(2),ones(3))
+%!error unidcdf (i, 2)
+%!error unidcdf (2, i)
+
--- a/scripts/statistics/distributions/unidinv.m
+++ b/scripts/statistics/distributions/unidinv.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 2007-2011 David Bateman
 ##
 ## This file is part of Octave.
@@ -17,25 +18,64 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} unidinv (@var{x}, @var{v})
-## For each component of @var{x}, compute the quantile (the inverse of
-## the CDF) at @var{x} of the discrete uniform distribution which assumes the
-## values in @var{v} with equal probability.
-## If @var{v} is a scalar then @code{1/@var{v}} is the probability of a
-## single element.
+## @deftypefn {Function File} {} unidinv (@var{x}, @var{n})
+## For each element of @var{x}, compute the quantile (the inverse of
+## the CDF) at @var{x} of the discrete uniform distribution which assumes
+## the integer values 1--@var{n} with equal probability.
 ## @end deftypefn
 
-function inv = unidinv (x, v)
+function inv = unidinv (x, n)
 
   if (nargin != 2)
     print_usage ();
   endif
 
-  if (isscalar(v))
-    v = [1:v].';
+  if (! isscalar (n))
+    [retval, x, n] = common_size (x, n);
+    if (retval > 0)
+      error ("unidcdf: X and N must be of common size or scalars");
+    endif
+  endif
+
+  if (iscomplex (x) || iscomplex (n))
+    error ("unidinv: X and N must not be complex");
+  endif
+
+  if (isa (x, "single") || isa (n, "single"))
+    inv = NaN (size (x), "single");
   else
-    v = v(:);
+    inv = NaN (size (x));
+  endif
+
+  ## For Matlab compatibility, unidinv(0) = NaN
+  k = (x > 0) & (x <= 1) & (n > 0 & n == fix (n));
+  if (isscalar (n))
+    inv(k) = floor (x(k) * n);
+  else
+    inv(k) = floor (x(k) .* n(k));
   endif
 
-  inv = discrete_inv (x, v, ones(size(v)));
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.5 1 2];
+%!assert(unidinv (x, 10*ones(1,5)), [NaN NaN 5 10 NaN], eps);
+%!assert(unidinv (x, 10), [NaN NaN 5 10 NaN], eps);
+%!assert(unidinv (x, 10*[0 1 NaN 1 1]), [NaN NaN NaN 10 NaN], eps);
+%!assert(unidinv ([x(1:2) NaN x(4:5)], 10), [NaN NaN NaN 10 NaN], eps);
+
+%% Test class of input preserved
+%!assert(unidinv ([x, NaN], 10), [NaN NaN 5 10 NaN NaN], eps);
+%!assert(unidinv (single([x, NaN]), 10), single([NaN NaN 5 10 NaN NaN]), eps);
+%!assert(unidinv ([x, NaN], single(10)), single([NaN NaN 5 10 NaN NaN]), eps);
+
+%% Test input validation
+%!error unidinv ()
+%!error unidinv (1)
+%!error unidinv (1,2,3)
+%!error unidinv (ones(3),ones(2))
+%!error unidinv (ones(2),ones(3))
+%!error unidinv (i, 2)
+%!error unidinv (2, i)
+
--- a/scripts/statistics/distributions/unidpdf.m
+++ b/scripts/statistics/distributions/unidpdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 2007-2011 David Bateman
 ##
 ## This file is part of Octave.
@@ -17,25 +18,70 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} unidpdf (@var{x}, @var{v})
+## @deftypefn {Function File} {} unidpdf (@var{x}, @var{n})
 ## For each element of @var{x}, compute the probability density function
 ## (PDF) at @var{x} of a discrete uniform distribution which assumes
-## the values in @var{v} with equal probability.
-## If @var{v} is a scalar then @code{1/@var{v}} is the probability of a
-## single element.
+## the integer values 1--@var{n} with equal probability.
+##
+## Warning: The underlying implementation uses the double class and
+## will only be accurate for @var{n} @leq{} @code{bitmax} 
+## (@w{@math{2^{53} - 1}} on IEEE-754 compatible systems).
 ## @end deftypefn
 
-function pdf = unidpdf (x, v)
+function pdf = unidpdf (x, n)
 
   if (nargin != 2)
     print_usage ();
   endif
 
-  if (isscalar(v))
-    v = [1:v].';
+  if (! isscalar (n))
+    [retval, x, n] = common_size (x, n);
+    if (retval > 0)
+      error ("unidpdf: X and N must be of common size or scalars");
+    endif
+  endif
+
+  if (iscomplex (x) || iscomplex (n))
+    error ("unidpdf: X and N must not be complex");
+  endif
+
+  if (isa (x, "single") || isa (n, "single"))
+    pdf = zeros (size (x), "single");
   else
-    v = v(:);
+    pdf = zeros (size (x));
   endif
 
-  pdf = discrete_pdf (x, v, ones(size(v)));
+  k = isnan (x) | ! (n > 0 & n == fix (n));
+  pdf(k) = NaN;
+
+  k = !k & (x >= 1) & (x <= n) & (x == fix (x));
+  if (isscalar (n))
+    pdf(k) = 1 / n;
+  else
+    pdf(k) = 1 ./ n(k);
+  endif
+
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 1 2 10 11];
+%! y = [0 0 0.1 0.1 0.1 0];
+%!assert(unidpdf (x, 10*ones(1,6)), y);
+%!assert(unidpdf (x, 10), y);
+%!assert(unidpdf (x, 10*[0 NaN 1 1 1 1]), [NaN NaN y(3:6)]);
+%!assert(unidpdf ([x, NaN], 10), [y, NaN]);
+
+%% Test class of input preserved
+%!assert(unidpdf (single([x, NaN]), 10), single([y, NaN]));
+%!assert(unidpdf ([x, NaN], single(10)), single([y, NaN]));
+
+%% Test input validation
+%!error unidpdf ()
+%!error unidpdf (1)
+%!error unidpdf (1,2,3)
+%!error unidpdf (ones(3),ones(2))
+%!error unidpdf (ones(2),ones(3))
+%!error unidpdf (i, 2)
+%!error unidpdf (2, i)
+
--- a/scripts/statistics/distributions/unidrnd.m
+++ b/scripts/statistics/distributions/unidrnd.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 2005-2011 John W. Eaton
 ##
 ## This file is part of Octave.
@@ -17,44 +18,94 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} unidrnd (@var{mx});
-## @deftypefnx {Function File} {} unidrnd (@var{mx}, @var{v});
-## @deftypefnx {Function File} {} unidrnd (@var{mx}, @var{m}, @var{n}, @dots{});
-## Return random values from a discrete uniform distribution with maximum
-## value(s) given by the integer @var{mx} (which may be a scalar or
-## multi-dimensional array).
+## @deftypefn  {Function File} {} unidrnd (@var{n})
+## @deftypefnx {Function File} {} unidrnd (@var{n}, @var{r})
+## @deftypefnx {Function File} {} unidrnd (@var{n}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} unidrnd (@var{n}, [@var{sz}])
+## Return a matrix of random samples from the discrete uniform distribution
+## which assumes the integer values 1--@var{n} with equal probability.
+## @var{n} may be a scalar or a multi-dimensional array.
 ##
-## If @var{mx} is a scalar, the size of the result is specified by
-## the vector @var{v}, or by the optional arguments @var{m}, @var{n},
-## @dots{}.  Otherwise, the size of the result is the same as the size
-## of @var{mx}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the size of
+## @var{n}.
 ## @end deftypefn
 
 ## Author: jwe
 
-function retval = unidrnd (n, varargin)
+function rnd = unidrnd (n, varargin)
+
+  if (nargin < 1)
+    print_usage ();
+  endif
+
   if (nargin == 1)
-    dims = size (n);
+    sz = size (n);
   elseif (nargin == 2)
-    if (rows (varargin{1}) == 1 && columns (varargin{1}) > 1)
-      dims = varargin{1};
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
     else
-      error ("unidrnd: invalid dimension vector");
+      error ("unidrnd: dimension vector must be row vector of non-negative integers");
     endif
   elseif (nargin > 2)
-    for i = 1:nargin-1
-      if (! isscalar (varargin{i}))
-        error ("unidrnd: expecting scalar dimensions");
-      endif
-    endfor
-    dims = [varargin{:}];
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("unidrnd: dimensions must be non-negative integers");
+    endif
+    sz = [varargin{:}];
+  endif
+
+  if (!isscalar (n) && !isequal (size (n), sz))
+    error ("unidrnd: N must be scalar or of size SZ");
+  endif
+
+  if (iscomplex (n))
+    error ("unidrnd: N must not be complex");
+  endif
+
+  if (isa (n, "single"))
+    cls = "single";
+  else
+    cls = "double";
+  endif
+
+  if (isscalar (n))
+    if (n > 0 && n == fix (n))
+      rnd = ceil (rand (sz) * n);
+    else
+      rnd = NaN (sz, cls);
+    endif
   else
-    print_usage ();
+    rnd = ceil (rand (sz) .* n);
+
+    k = ! (n > 0 & n == fix (n));
+    rnd(k) = NaN;
   endif
-  if (isscalar (n)
-      || (length (size (n)) == length (dims) && all (size (n) == dims)))
-    retval = ceil (rand (dims) .* n);
-  else
-    error ("unidrnd: dimension mismatch");
-  endif
+
 endfunction
+
+
+%!assert(size (unidrnd (2)), [1, 1]);
+%!assert(size (unidrnd (ones(2,1))), [2, 1]);
+%!assert(size (unidrnd (ones(2,2))), [2, 2]);
+%!assert(size (unidrnd (10, [4 1])), [4, 1]);
+%!assert(size (unidrnd (10, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (unidrnd (2)), "double");
+%!assert(class (unidrnd (single(2))), "single");
+%!assert(class (unidrnd (single([2 2]))), "single");
+
+%% Test input validation
+%!error unidrnd ()
+%!error unidrnd (10, [1;2;3])
+%!error unidrnd (10, 2, ones(2))
+%!error unidrnd (10*ones(2), 2, 1)
+%!error unidrnd (i)
+
--- a/scripts/statistics/distributions/unifcdf.m
+++ b/scripts/statistics/distributions/unifcdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,9 +18,11 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} unifcdf (@var{x}, @var{a}, @var{b})
-## Return the CDF at @var{x} of the uniform distribution on [@var{a},
-## @var{b}], i.e., PROB (uniform (@var{a}, @var{b}) @leq{} x).
+## @deftypefn  {Function File} {} unifcdf (@var{x})
+## @deftypefnx {Function File} {} unifcdf (@var{x}, @var{a}, @var{b})
+## For each element of @var{x}, compute the cumulative distribution
+## function (CDF) at @var{x} of the uniform distribution on the interval
+## [@var{a}, @var{b}].
 ##
 ## Default values are @var{a} = 0, @var{b} = 1.
 ## @end deftypefn
@@ -27,44 +30,69 @@
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: CDF of the uniform distribution
 
-function cdf = unifcdf (x, a, b)
+function cdf = unifcdf (x, a = 0, b = 1)
 
   if (nargin != 1 && nargin != 3)
     print_usage ();
   endif
 
-  if (nargin == 1)
-    a = 0;
-    b = 1;
-  endif
-
-  if (!isscalar (a) || !isscalar(b))
+  if (!isscalar (a) || !isscalar (b))
     [retval, x, a, b] = common_size (x, a, b);
     if (retval > 0)
-      error ("unifcdf: X, A and B must be of common size or scalar");
+      error ("unifcdf: X, A, and B must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  cdf = zeros (sz);
+  if (iscomplex (x) || iscomplex (a) || iscomplex (b))
+    error ("unifcdf: X, A, and B must not be complex");
+  endif
 
-  k = find (isnan (x) | !(a < b));
-  if (any (k))
-    cdf(k) = NaN;
+  if (isa (x, "single") || isa (a, "single") || isa (b, "single"))
+    cdf = zeros (size (x), "single");
+  else
+    cdf = zeros (size (x));
   endif
 
-  k = find ((x >= b) & (a < b));
-  if (any (k))
-    cdf(k) = 1;
-  endif
+  k = isnan (x) | !(a < b);
+  cdf(k) = NaN;
+
+  k = (x >= b) & (a < b);
+  cdf(k) = 1;
 
-  k = find ((x > a) & (x < b));
-  if (any (k))
-    if (isscalar (a) && isscalar(b))
-      cdf(k) = (x(k) < b) .* (x(k) - a) ./ (b - a);
-    else
-      cdf(k) = (x(k) < b(k)) .* (x(k) - a(k)) ./ (b(k) - a(k));
-    endif
+  k = (x > a) & (x < b);
+  if (isscalar (a) && isscalar (b))
+    cdf(k) = (x(k) < b) .* (x(k) - a) / (b - a);
+  else
+    cdf(k) = (x(k) < b(k)) .* (x(k) - a(k)) ./ (b(k) - a(k));
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 0.5 1 2] + 1;
+%! y = [0 0 0.5 1 1];
+%!assert(unifcdf (x, ones(1,5), 2*ones(1,5)), y);
+%!assert(unifcdf (x, 1, 2*ones(1,5)), y);
+%!assert(unifcdf (x, ones(1,5), 2), y);
+%!assert(unifcdf (x, [2 1 NaN 1 1], 2), [NaN 0 NaN 1 1]);
+%!assert(unifcdf (x, 1, 2*[0 1 NaN 1 1]), [NaN 0 NaN 1 1]);
+%!assert(unifcdf ([x(1:2) NaN x(4:5)], 1, 2), [y(1:2) NaN y(4:5)]);
+
+%% Test class of input preserved
+%!assert(unifcdf ([x, NaN], 1, 2), [y, NaN]);
+%!assert(unifcdf (single([x, NaN]), 1, 2), single([y, NaN]));
+%!assert(unifcdf ([x, NaN], single(1), 2), single([y, NaN]));
+%!assert(unifcdf ([x, NaN], 1, single(2)), single([y, NaN]));
+
+%% Test input validation
+%!error unifcdf ()
+%!error unifcdf (1,2)
+%!error unifcdf (1,2,3,4)
+%!error unifcdf (ones(3),ones(2),ones(2))
+%!error unifcdf (ones(2),ones(3),ones(2))
+%!error unifcdf (ones(2),ones(2),ones(3))
+%!error unifcdf (i, 2, 2)
+%!error unifcdf (2, i, 2)
+%!error unifcdf (2, 2, i)
+
--- a/scripts/statistics/distributions/unifinv.m
+++ b/scripts/statistics/distributions/unifinv.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,9 +18,11 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} unifinv (@var{x}, @var{a}, @var{b})
+## @deftypefn  {Function File} {} unifinv (@var{x})
+## @deftypefnx {Function File} {} unifinv (@var{x}, @var{a}, @var{b})
 ## For each element of @var{x}, compute the quantile (the inverse of the
-## CDF) at @var{x} of the uniform distribution on [@var{a}, @var{b}].
+## CDF) at @var{x} of the uniform distribution on the interval
+## [@var{a}, @var{b}].
 ##
 ## Default values are @var{a} = 0, @var{b} = 1.
 ## @end deftypefn
@@ -27,39 +30,62 @@
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Quantile function of the uniform distribution
 
-function inv = unifinv (x, a, b)
+function inv = unifinv (x, a = 0, b = 1)
 
   if (nargin != 1 && nargin != 3)
     print_usage ();
   endif
 
-  if (nargin == 1)
-    a = 0;
-    b = 1;
-  endif
-
-  if (!isscalar (a) || !isscalar(b))
+  if (!isscalar (a) || !isscalar (b))
     [retval, x, a, b] = common_size (x, a, b);
     if (retval > 0)
-      error ("unifinv: X, A and B must be of common size or scalar");
+      error ("unifinv: X, A, and B must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  inv = zeros (sz);
-
-  k = find ((x < 0) | (x > 1) | isnan (x) | !(a < b));
-  if (any (k))
-    inv(k) = NaN;
+  if (iscomplex (x) || iscomplex (a) || iscomplex (b))
+    error ("unifinv: X, A, and B must not be complex");
   endif
 
-  k = find ((x >= 0) & (x <= 1) & (a < b));
-  if (any (k))
-    if (isscalar (a) && isscalar(b))
-      inv(k) = a + x(k) .* (b - a);
-    else
-      inv(k) = a(k) + x(k) .* (b(k) - a(k));
-    endif
+  if (isa (x, "single") || isa (a, "single") || isa (b, "single"))
+    inv = NaN (size (x), "single");
+  else
+    inv = NaN (size (x));
+  endif
+
+  k = (x >= 0) & (x <= 1) & (a < b);
+  if (isscalar (a) && isscalar (b))
+    inv(k) = a + x(k) * (b - a);
+  else
+    inv(k) = a(k) + x(k) .* (b(k) - a(k));
   endif
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.5 1 2];
+%!assert(unifinv (x, ones(1,5), 2*ones(1,5)), [NaN 1 1.5 2 NaN]);
+%!assert(unifinv (x, 1, 2*ones(1,5)), [NaN 1 1.5 2 NaN]);
+%!assert(unifinv (x, ones(1,5), 2), [NaN 1 1.5 2 NaN]);
+%!assert(unifinv (x, [1 2 NaN 1 1], 2), [NaN NaN NaN 2 NaN]);
+%!assert(unifinv (x, 1, 2*[1 0 NaN 1 1]), [NaN NaN NaN 2 NaN]);
+%!assert(unifinv ([x(1:2) NaN x(4:5)], 1, 2), [NaN 1 NaN 2 NaN]);
+
+%% Test class of input preserved
+%!assert(unifinv ([x, NaN], 1, 2), [NaN 1 1.5 2 NaN NaN]);
+%!assert(unifinv (single([x, NaN]), 1, 2), single([NaN 1 1.5 2 NaN NaN]));
+%!assert(unifinv ([x, NaN], single(1), 2), single([NaN 1 1.5 2 NaN NaN]));
+%!assert(unifinv ([x, NaN], 1, single(2)), single([NaN 1 1.5 2 NaN NaN]));
+
+%% Test input validation
+%!error unifinv ()
+%!error unifinv (1,2)
+%!error unifinv (1,2,3,4)
+%!error unifinv (ones(3),ones(2),ones(2))
+%!error unifinv (ones(2),ones(3),ones(2))
+%!error unifinv (ones(2),ones(2),ones(3))
+%!error unifinv (i, 2, 2)
+%!error unifinv (2, i, 2)
+%!error unifinv (2, 2, i)
+
--- a/scripts/statistics/distributions/unifpdf.m
+++ b/scripts/statistics/distributions/unifpdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,9 +18,10 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} unifpdf (@var{x}, @var{a}, @var{b})
-## For each element of @var{x}, compute the PDF at @var{x} of the uniform
-## distribution on [@var{a}, @var{b}].
+## @deftypefn  {Function File} {} unifpdf (@var{x})
+## @deftypefnx {Function File} {} unifpdf (@var{x}, @var{a}, @var{b})
+## For each element of @var{x}, compute the probability density function (PDF)
+## at @var{x} of the uniform distribution on the interval [@var{a}, @var{b}].
 ##
 ## Default values are @var{a} = 0, @var{b} = 1.
 ## @end deftypefn
@@ -27,39 +29,65 @@
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: PDF of the uniform distribution
 
-function pdf = unifpdf (x, a, b)
+function pdf = unifpdf (x, a = 0, b = 1)
 
   if (nargin != 1 && nargin != 3)
     print_usage ();
   endif
 
-  if (nargin == 1)
-    a = 0;
-    b = 1;
-  endif
-
-  if (!isscalar (a) || !isscalar(b))
+  if (!isscalar (a) || !isscalar (b))
     [retval, x, a, b] = common_size (x, a, b);
     if (retval > 0)
-      error ("unifpdf: X, A and B must be of common size or scalars");
+      error ("unifpdf: X, A, and B must be of common size or scalars");
     endif
   endif
 
-  sz = size (x);
-  pdf = zeros (sz);
-
-  k = find (isnan (x) | !(a < b));
-  if (any (k))
-    pdf(k) = NaN;
+  if (iscomplex (x) || iscomplex (a) || iscomplex (b))
+    error ("unifpdf: X, A, and B must not be complex");
   endif
 
-  k = find ((x >= a) & (x <= b));
-  if (any (k))
-    if (isscalar (a) && isscalar(b))
-      pdf(k) = 1 ./ (b - a);
-    else
-      pdf(k) = 1 ./ (b(k) - a(k));
-    endif
+  if (isa (x, "single") || isa (a, "single") || isa (b, "single"))
+    pdf = zeros (size (x), "single");
+  else
+    pdf = zeros (size (x));
+  endif
+
+  k = isnan (x) | !(a < b);
+  pdf(k) = NaN;
+
+  k = (x >= a) & (x <= b) & (a < b);
+  if (isscalar (a) && isscalar (b))
+    pdf(k) = 1 / (b - a);
+  else
+    pdf(k) = 1 ./ (b(k) - a(k));
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 0.5 1 2] + 1;
+%! y = [0 1 1 1 0];
+%!assert(unifpdf (x, ones(1,5), 2*ones(1,5)), y);
+%!assert(unifpdf (x, 1, 2*ones(1,5)), y);
+%!assert(unifpdf (x, ones(1,5), 2), y);
+%!assert(unifpdf (x, [2 NaN 1 1 1], 2), [NaN NaN y(3:5)]);
+%!assert(unifpdf (x, 1, 2*[0 NaN 1 1 1]), [NaN NaN y(3:5)]);
+%!assert(unifpdf ([x, NaN], 1, 2), [y, NaN]);
+
+%% Test class of input preserved
+%!assert(unifpdf (single([x, NaN]), 1, 2), single([y, NaN]));
+%!assert(unifpdf (single([x, NaN]), single(1), 2), single([y, NaN]));
+%!assert(unifpdf ([x, NaN], 1, single(2)), single([y, NaN]));
+
+%% Test input validation
+%!error unifpdf ()
+%!error unifpdf (1,2)
+%!error unifpdf (1,2,3,4)
+%!error unifpdf (ones(3),ones(2),ones(2))
+%!error unifpdf (ones(2),ones(3),ones(2))
+%!error unifpdf (ones(2),ones(2),ones(3))
+%!error unifpdf (i, 2, 2)
+%!error unifpdf (2, i, 2)
+%!error unifpdf (2, 2, i)
+
--- a/scripts/statistics/distributions/unifrnd.m
+++ b/scripts/statistics/distributions/unifrnd.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,75 +18,115 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} unifrnd (@var{a}, @var{b}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} unifrnd (@var{a}, @var{b}, @var{sz})
-## Return an @var{r} by @var{c} or a @code{size (@var{sz})} matrix of
-## random samples from the uniform distribution on [@var{a}, @var{b}].
-## Both @var{a} and @var{b} must be scalar or of size @var{r} by @var{c}.
+## @deftypefn  {Function File} {} unifrnd (@var{a}, @var{b})
+## @deftypefnx {Function File} {} unifrnd (@var{a}, @var{b}, @var{r})
+## @deftypefnx {Function File} {} unifrnd (@var{a}, @var{b}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} unifrnd (@var{a}, @var{b}, [@var{sz}])
+## Return a matrix of random samples from the uniform distribution on
+## [@var{a}, @var{b}].
 ##
-## If @var{r} and @var{c} are omitted, the size of the result matrix is
-## the common size of @var{a} and @var{b}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the common size of
+## @var{a} and @var{b}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the uniform distribution
 
-function rnd = unifrnd (a, b, r, c)
+function rnd = unifrnd (a, b, varargin)
 
-  if (nargin > 1)
-    if (!isscalar(a) || !isscalar(b))
-      [retval, a, b] = common_size (a, b);
-      if (retval > 0)
-        error ("unifrnd: A and B must be of common size or scalar");
-      endif
+  if (nargin < 2)
+    print_usage ();
+  endif
+
+  if (!isscalar (a) || !isscalar (b))
+    [retval, a, b] = common_size (a, b);
+    if (retval > 0)
+      error ("unifrnd: A and B must be of common size or scalars");
     endif
   endif
 
-  if (nargin == 4)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("unifrnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("unifrnd: C must be a positive integer");
-    endif
-    sz = [r, c];
-
-    if (any (size (a) != 1)
-        && (length (size (a)) != length (sz) || any (size (a) != sz)))
-      error ("unifrnd: A and B must be scalar or of size [R, C]");
-    endif
-  elseif (nargin == 3)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
-    else
-      error ("unifrnd: R must be a positive integer or vector");
-    endif
-
-    if (any (size (a) != 1)
-        && (length (size (a)) != length (sz) || any (size (a) != sz)))
-      error ("unifrnd: A and B must be scalar or of size SZ");
-    endif
-  elseif (nargin == 2)
-    sz = size(a);
-  else
-    print_usage ();
+  if (iscomplex (a) || iscomplex (b))
+    error ("unifrnd: A and B must not be complex");
   endif
 
-  if (isscalar(a) && isscalar(b))
-    if (find (!(-Inf < a) | !(a < b) | !(b < Inf)))
-      rnd = NaN(sz);
+  if (nargin == 2)
+    sz = size (a);
+  elseif (nargin == 3)
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
     else
-      rnd =  a + (b - a) .* rand (sz);
+      error ("unifrnd: dimension vector must be row vector of non-negative integers");
+    endif
+  elseif (nargin > 3)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("unifrnd: dimensions must be non-negative integers");
+    endif
+    sz = [varargin{:}];
+  endif
+
+  if (!isscalar (a) && !isequal (size (a), sz))
+    error ("unifrnd: A and B must be scalar or of size SZ");
+  endif
+
+  if (isa (a, "single") || isa (b, "single"))
+    cls = "single";
+  else
+    cls = "double";
+  endif
+
+  if (isscalar (a) && isscalar (b))
+    if ((-Inf < a) && (a < b) && (b < Inf))
+      rnd =  a + (b - a) * rand (sz);
+    else
+      rnd = NaN (sz, cls);
     endif
   else
     rnd =  a + (b - a) .* rand (sz);
 
-    k = find (!(-Inf < a) | !(a < b) | !(b < Inf));
-    if (any (k))
-      rnd(k) = NaN;
-    endif
+    k = !(-Inf < a) | !(a < b) | !(b < Inf);
+    rnd(k) = NaN;
   endif
 
 endfunction
+
+
+%!assert(size (unifrnd (1,2)), [1, 1]);
+%!assert(size (unifrnd (ones(2,1), 2)), [2, 1]);
+%!assert(size (unifrnd (ones(2,2), 2)), [2, 2]);
+%!assert(size (unifrnd (1, 2*ones(2,1))), [2, 1]);
+%!assert(size (unifrnd (1, 2*ones(2,2))), [2, 2]);
+%!assert(size (unifrnd (1, 2, 3)), [3, 3]);
+%!assert(size (unifrnd (1, 2, [4 1])), [4, 1]);
+%!assert(size (unifrnd (1, 2, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (unifrnd (1, 2)), "double");
+%!assert(class (unifrnd (single(1), 2)), "single");
+%!assert(class (unifrnd (single([1 1]), 2)), "single");
+%!assert(class (unifrnd (1, single(2))), "single");
+%!assert(class (unifrnd (1, single([2 2]))), "single");
+
+%% Test input validation
+%!error unifrnd ()
+%!error unifrnd (1)
+%!error unifrnd (ones(3),ones(2))
+%!error unifrnd (ones(2),ones(3))
+%!error unifrnd (i, 2)
+%!error unifrnd (2, i)
+%!error unifrnd (1,2, -1)
+%!error unifrnd (1,2, ones(2))
+%!error unifrnd (1, 2, [2 -1 2])
+%!error unifrnd (1,2, 1, ones(2))
+%!error unifrnd (1,2, 1, -1)
+%!error unifrnd (ones(2,2), 2, 3)
+%!error unifrnd (ones(2,2), 2, [3, 2])
+%!error unifrnd (ones(2,2), 2, 2, 3)
+
--- a/scripts/statistics/distributions/wblcdf.m
+++ b/scripts/statistics/distributions/wblcdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,7 +18,9 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} wblcdf (@var{x}, @var{scale}, @var{shape})
+## @deftypefn  {Function File} {} wblcdf (@var{x})
+## @deftypefnx {Function File} {} wblcdf (@var{x}, @var{scale})
+## @deftypefnx {Function File} {} wblcdf (@var{x}, @var{scale}, @var{shape})
 ## Compute the cumulative distribution function (CDF) at @var{x} of the
 ## Weibull distribution with scale parameter @var{scale} and shape
 ## parameter @var{shape}, which is
@@ -28,59 +31,83 @@
 ## @ifnottex
 ##
 ## @example
-## 1 - exp(-(x/scale)^shape)
+## 1 - exp (-(x/scale)^shape)
 ## @end example
 ##
 ## @noindent
 ## for @var{x} @geq{} 0.
+##
+## Default values are @var{scale} = 1, @var{shape} = 1.
 ## @end ifnottex
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: CDF of the Weibull distribution
 
-function cdf = wblcdf (x, scale, shape)
+function cdf = wblcdf (x, scale = 1, shape = 1)
 
   if (nargin < 1 || nargin > 3)
     print_usage ();
   endif
 
-  if (nargin < 3)
-    shape = 1;
-  endif
-
-  if (nargin < 2)
-    scale = 1;
-  endif
-
   if (!isscalar (shape) || !isscalar (scale))
     [retval, x, shape, scale] = common_size (x, shape, scale);
     if (retval > 0)
-      error ("wblcdf: X, SCALE and SHAPE must be of common size or scalar");
+      error ("wblcdf: X, SCALE, and SHAPE must be of common size or scalars");
     endif
   endif
 
-  cdf = NaN (size (x));
-
-  ok = ((shape > 0) & (shape < Inf) & (scale > 0) & (scale < Inf));
+  if (iscomplex (x) || iscomplex (scale) || iscomplex (shape))
+    error ("wblcdf: X, SCALE, and SHAPE must not be complex");
+  endif
 
-  k = find ((x <= 0) & ok);
-  if (any (k))
-    cdf(k) = 0;
+  if (isa (x, "single") || isa (scale, "single") || isa (shape, "single"))
+    cdf = NaN (size (x), "single");
+  else
+    cdf = NaN (size (x));
   endif
 
-  k = find ((x > 0) & (x < Inf) & ok);
-  if (any (k))
-    if (isscalar (shape) && isscalar (scale))
-      cdf(k) = 1 - exp (- (x(k) / scale) .^ shape);
-    else
-      cdf(k) = 1 - exp (- (x(k) ./ scale(k)) .^ shape(k));
-    endif
-  endif
+  ok = (shape > 0) & (shape < Inf) & (scale > 0) & (scale < Inf);
+
+  k = (x <= 0) & ok;
+  cdf(k) = 0;
 
-  k = find ((x == Inf) & ok);
-  if (any (k))
-    cdf(k) = 1;
+  k = (x == Inf) & ok;
+  cdf(k) = 1;
+
+  k = (x > 0) & (x < Inf) & ok;
+  if (isscalar (shape) && isscalar (scale))
+    cdf(k) = 1 - exp (- (x(k) / scale) .^ shape);
+  else
+    cdf(k) = 1 - exp (- (x(k) ./ scale(k)) .^ shape(k));
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 0.5 1 Inf];
+%! y = [0, 1-exp(-x(2:4)), 1];
+%!assert(wblcdf (x, ones(1,5), ones(1,5)), y);
+%!assert(wblcdf (x, 1, ones(1,5)), y);
+%!assert(wblcdf (x, ones(1,5), 1), y);
+%!assert(wblcdf (x, [0 1 NaN Inf 1], 1), [NaN 0 NaN NaN 1]);
+%!assert(wblcdf (x, 1, [0 1 NaN Inf 1]), [NaN 0 NaN NaN 1]);
+%!assert(wblcdf ([x(1:2) NaN x(4:5)], 1, 1), [y(1:2) NaN y(4:5)]);
+
+%% Test class of input preserved
+%!assert(wblcdf ([x, NaN], 1, 1), [y, NaN]);
+%!assert(wblcdf (single([x, NaN]), 1, 1), single([y, NaN]));
+%!assert(wblcdf ([x, NaN], single(1), 1), single([y, NaN]));
+%!assert(wblcdf ([x, NaN], 1, single(1)), single([y, NaN]));
+
+%% Test input validation
+%!error wblcdf ()
+%!error wblcdf (1,2,3,4)
+%!error wblcdf (ones(3),ones(2),ones(2))
+%!error wblcdf (ones(2),ones(3),ones(2))
+%!error wblcdf (ones(2),ones(2),ones(3))
+%!error wblcdf (i, 2, 2)
+%!error wblcdf (2, i, 2)
+%!error wblcdf (2, 2, i)
+
--- a/scripts/statistics/distributions/wblinv.m
+++ b/scripts/statistics/distributions/wblinv.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,57 +18,82 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} wblinv (@var{x}, @var{scale}, @var{shape})
+## @deftypefn  {Function File} {} wblinv (@var{x})
+## @deftypefnx {Function File} {} wblinv (@var{x}, @var{scale})
+## @deftypefnx {Function File} {} wblinv (@var{x}, @var{scale}, @var{shape})
 ## Compute the quantile (the inverse of the CDF) at @var{x} of the
 ## Weibull distribution with scale parameter @var{scale} and shape
 ## parameter @var{shape}.
+##
+## Default values are @var{scale} = 1, @var{shape} = 1.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Quantile function of the Weibull distribution
 
-function inv = wblinv (x, scale, shape)
+function inv = wblinv (x, scale = 1, shape = 1)
 
   if (nargin < 1 || nargin > 3)
     print_usage ();
   endif
 
-  if (nargin < 3)
-    shape = 1;
-  endif
-
-  if (nargin < 2)
-    scale = 1;
-  endif
-
   if (!isscalar (scale) || !isscalar (shape))
     [retval, x, scale, shape] = common_size (x, scale, shape);
     if (retval > 0)
-      error ("wblinv: X, SCALE and SHAPE must be of common size or scalar");
+      error ("wblinv: X, SCALE, and SHAPE must be of common size or scalars");
     endif
   endif
 
-  inv = NaN (size (x));
-
-  ok = ((scale > 0) & (scale < Inf) & (shape > 0) & (shape < Inf));
+  if (iscomplex (x) || iscomplex (scale) || iscomplex (shape))
+    error ("wblinv: X, SCALE, and SHAPE must not be complex");
+  endif
 
-  k = find ((x == 0) & ok);
-  if (any (k))
-    inv(k) = 0;
+  if (isa (x, "single") || isa (scale, "single") || isa (shape, "single"))
+    inv = NaN (size (x), "single");
+  else
+    inv = NaN (size (x));
   endif
 
-  k = find ((x > 0) & (x < 1) & ok);
-  if (any (k))
-    if (isscalar (scale) && isscalar (shape))
-      inv(k) = scale * (- log (1 - x(k))) .^ (1 / shape);
-    else
-      inv(k) = scale(k) .* (- log (1 - x(k))) .^ (1 ./ shape(k));
-    endif
-  endif
+  ok = (scale > 0) & (scale < Inf) & (shape > 0) & (shape < Inf);
+
+  k = (x == 0) & ok;
+  inv(k) = 0;
 
-  k = find ((x == 1) & ok);
-  if (any (k))
-    inv(k) = Inf;
+  k = (x == 1) & ok;
+  inv(k) = Inf;
+
+  k = (x > 0) & (x < 1) & ok;
+  if (isscalar (scale) && isscalar (shape))
+    inv(k) = scale * (- log (1 - x(k))) .^ (1 / shape);
+  else
+    inv(k) = scale(k) .* (- log (1 - x(k))) .^ (1 ./ shape(k));
   endif
 
 endfunction
+
+
+%!shared x
+%! x = [-1 0 0.63212055882855778 1 2];
+%!assert(wblinv (x, ones(1,5), ones(1,5)), [NaN 0 1 Inf NaN], eps);
+%!assert(wblinv (x, 1, ones(1,5)), [NaN 0 1 Inf NaN], eps);
+%!assert(wblinv (x, ones(1,5), 1), [NaN 0 1 Inf NaN], eps);
+%!assert(wblinv (x, [1 -1 NaN Inf 1], 1), [NaN NaN NaN NaN NaN]);
+%!assert(wblinv (x, 1, [1 -1 NaN Inf 1]), [NaN NaN NaN NaN NaN]);
+%!assert(wblinv ([x(1:2) NaN x(4:5)], 1, 1), [NaN 0 NaN Inf NaN]);
+
+%% Test class of input preserved
+%!assert(wblinv ([x, NaN], 1, 1), [NaN 0 1 Inf NaN NaN], eps);
+%!assert(wblinv (single([x, NaN]), 1, 1), single([NaN 0 1 Inf NaN NaN]), eps("single"));
+%!assert(wblinv ([x, NaN], single(1), 1), single([NaN 0 1 Inf NaN NaN]), eps("single"));
+%!assert(wblinv ([x, NaN], 1, single(1)), single([NaN 0 1 Inf NaN NaN]), eps("single"));
+
+%% Test input validation
+%!error wblinv ()
+%!error wblinv (1,2,3,4)
+%!error wblinv (ones(3),ones(2),ones(2))
+%!error wblinv (ones(2),ones(3),ones(2))
+%!error wblinv (ones(2),ones(2),ones(3))
+%!error wblinv (i, 2, 2)
+%!error wblinv (2, i, 2)
+%!error wblinv (2, 2, i)
+
--- a/scripts/statistics/distributions/wblpdf.m
+++ b/scripts/statistics/distributions/wblpdf.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,7 +18,9 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} wblpdf (@var{x}, @var{scale}, @var{shape})
+## @deftypefn  {Function File} {} wblpdf (@var{x})
+## @deftypefnx {Function File} {} wblpdf (@var{x}, @var{scale})
+## @deftypefnx {Function File} {} wblpdf (@var{x}, @var{scale}, @var{shape})
 ## Compute the probability density function (PDF) at @var{x} of the
 ## Weibull distribution with scale parameter @var{scale} and shape
 ## parameter @var{shape} which is given by
@@ -27,57 +30,83 @@
 ## @ifnottex
 ##
 ## @example
-##    shape * scale^(-shape) * x^(shape-1) * exp(-(x/scale)^shape)
+##    shape * scale^(-shape) * x^(shape-1) * exp (-(x/scale)^shape)
 ## @end example
 ##
 ## @end ifnottex
 ## @noindent
 ## for @var{x} @geq{} 0.
+##
+## Default values are @var{scale} = 1, @var{shape} = 1.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: PDF of the Weibull distribution
 
-function pdf = wblpdf (x, scale, shape)
+function pdf = wblpdf (x, scale = 1, shape = 1)
 
   if (nargin < 1 || nargin > 3)
     print_usage ();
   endif
 
-  if (nargin < 3)
-    shape = 1;
-  endif
-
-  if (nargin < 2)
-    scale = 1;
-  endif
-
   if (!isscalar (scale) || !isscalar (shape))
     [retval, x, scale, shape] = common_size (x, scale, shape);
     if (retval > 0)
-      error ("wblpdf: X, SCALE and SHAPE must be of common size or scalar");
+      error ("wblpdf: X, SCALE, and SHAPE must be of common size or scalars");
     endif
   endif
 
-  pdf = NaN (size (x));
-  ok = ((scale > 0) & (scale < Inf) & (shape > 0) & (shape < Inf));
+  if (iscomplex (x) || iscomplex (scale) || iscomplex (shape))
+    error ("wblpdf: X, SCALE, and SHAPE must not be complex");
+  endif
 
-  k = find ((x > -Inf) & (x < 0) & ok);
-  if (any (k))
-    pdf(k) = 0;
+  if (isa (x, "single") || isa (scale, "single") || isa (shape, "single"))
+    pdf = NaN (size (x), "single");
+  else
+    pdf = NaN (size (x));
   endif
 
-  k = find ((x >= 0) & (x < Inf) & ok);
-  if (any (k))
-    if (isscalar (scale) && isscalar (shape))
-      pdf(k) = (shape .* (scale .^ -shape)
-                .* (x(k) .^ (shape - 1))
-                .* exp(- (x(k) / scale) .^ shape));
-    else
-      pdf(k) = (shape(k) .* (scale(k) .^ -shape(k))
-                .* (x(k) .^ (shape(k) - 1))
-                .* exp(- (x(k) ./ scale(k)) .^ shape(k)));
-    endif
+  ok = ((scale > 0) & (scale < Inf) & (shape > 0) & (shape < Inf));
+
+  k = (x < 0) & ok;
+  pdf(k) = 0;
+
+  k = (x >= 0) & (x < Inf) & ok;
+  if (isscalar (scale) && isscalar (shape))
+    pdf(k) = (shape * (scale .^ -shape)
+              .* (x(k) .^ (shape - 1))
+              .* exp (- (x(k) / scale) .^ shape));
+  else
+    pdf(k) = (shape(k) .* (scale(k) .^ -shape(k))
+              .* (x(k) .^ (shape(k) - 1))
+              .* exp (- (x(k) ./ scale(k)) .^ shape(k)));
   endif
 
 endfunction
+
+
+%!shared x,y
+%! x = [-1 0 0.5 1 Inf];
+%! y = [0, exp(-x(2:4)), NaN];
+%!assert(wblpdf (x, ones(1,5), ones(1,5)), y);
+%!assert(wblpdf (x, 1, ones(1,5)), y);
+%!assert(wblpdf (x, ones(1,5), 1), y);
+%!assert(wblpdf (x, [0 NaN Inf 1 1], 1), [NaN NaN NaN y(4:5)]);
+%!assert(wblpdf (x, 1, [0 NaN Inf 1 1]), [NaN NaN NaN y(4:5)]);
+%!assert(wblpdf ([x, NaN], 1, 1), [y, NaN]);
+
+%% Test class of input preserved
+%!assert(wblpdf (single([x, NaN]), 1, 1), single([y, NaN]));
+%!assert(wblpdf ([x, NaN], single(1), 1), single([y, NaN]));
+%!assert(wblpdf ([x, NaN], 1, single(1)), single([y, NaN]));
+
+%% Test input validation
+%!error wblpdf ()
+%!error wblpdf (1,2,3,4)
+%!error wblpdf (ones(3),ones(2),ones(2))
+%!error wblpdf (ones(2),ones(3),ones(2))
+%!error wblpdf (ones(2),ones(2),ones(3))
+%!error wblpdf (i, 2, 2)
+%!error wblpdf (2, i, 2)
+%!error wblpdf (2, 2, i)
+
--- a/scripts/statistics/distributions/wblrnd.m
+++ b/scripts/statistics/distributions/wblrnd.m
@@ -1,3 +1,4 @@
+## Copyright (C) 2011 Rik Wehbring
 ## Copyright (C) 1995-2011 Kurt Hornik
 ##
 ## This file is part of Octave.
@@ -17,78 +18,115 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} wblrnd (@var{scale}, @var{shape}, @var{r}, @var{c})
-## @deftypefnx {Function File} {} wblrnd (@var{scale}, @var{shape}, @var{sz})
-## Return an @var{r} by @var{c} matrix of random samples from the
-## Weibull distribution with parameters @var{scale} and @var{shape}
-## which must be scalar or of size @var{r} by @var{c}.  Or if @var{sz}
-## is a vector return a matrix of size @var{sz}.
+## @deftypefn  {Function File} {} wblrnd (@var{scale}, @var{shape})
+## @deftypefnx {Function File} {} wblrnd (@var{scale}, @var{shape}, @var{r})
+## @deftypefnx {Function File} {} wblrnd (@var{scale}, @var{shape}, @var{r}, @var{c}, @dots{})
+## @deftypefnx {Function File} {} wblrnd (@var{scale}, @var{shape}, [@var{sz}])
+## Return a matrix of random samples from the Weibull distribution with
+## parameters @var{scale} and @var{shape}.
 ##
-## If @var{r} and @var{c} are omitted, the size of the result matrix is
-## the common size of @var{alpha} and @var{sigma}.
+## When called with a single size argument, return a square matrix with
+## the dimension specified.  When called with more than one scalar argument the
+## first two arguments are taken as the number of rows and columns and any
+## further arguments specify additional matrix dimensions.  The size may also
+## be specified with a vector of dimensions @var{sz}.
+## 
+## If no size arguments are given then the result matrix is the common size of
+## @var{scale} and @var{shape}.
 ## @end deftypefn
 
 ## Author: KH <Kurt.Hornik@wu-wien.ac.at>
 ## Description: Random deviates from the Weibull distribution
 
-function rnd = wblrnd (scale, shape, r, c)
+function rnd = wblrnd (scale, shape, varargin)
 
-  if (nargin > 1)
-    if (!isscalar(scale) || !isscalar(shape))
-      [retval, scale, shape] = common_size (scale, shape);
-      if (retval > 0)
-        error ("wblrnd: SCALE and SHAPE must be of common size or scalar");
-      endif
+  if (nargin < 2)
+    print_usage ();
+  endif
+
+  if (!isscalar (scale) || !isscalar (shape))
+    [retval, scale, shape] = common_size (scale, shape);
+    if (retval > 0)
+      error ("wblrnd: SCALE and SHAPE must be of common size or scalars");
     endif
   endif
 
-  if (nargin == 4)
-    if (! (isscalar (r) && (r > 0) && (r == round (r))))
-      error ("wblrnd: R must be a positive integer");
-    endif
-    if (! (isscalar (c) && (c > 0) && (c == round (c))))
-      error ("wblrnd: C must be a positive integer");
-    endif
-    sz = [r, c];
+  if (iscomplex (scale) || iscomplex (shape))
+    error ("wblrnd: SCALE and SHAPE must not be complex");
+  endif
 
-    if (any (size (scale) != 1)
-        && ((length (size (scale)) != length (sz))
-            || any (size (scale) != sz)))
-      error ("wblrnd: SCALE and SHAPE must be scalar or of size [R, C]");
-    endif
+  if (nargin == 2)
+    sz = size (scale);
   elseif (nargin == 3)
-    if (isscalar (r) && (r > 0))
-      sz = [r, r];
-    elseif (isvector(r) && all (r > 0))
-      sz = r(:)';
+    if (isscalar (varargin{1}) && varargin{1} >= 0)
+      sz = [varargin{1}, varargin{1}];
+    elseif (isrow (varargin{1}) && all (varargin{1} >= 0))
+      sz = varargin{1};
     else
-      error ("wblrnd: R must be a positive integer or vector");
+      error ("wblrnd: dimension vector must be row vector of non-negative integers");
     endif
+  elseif (nargin > 3)
+    if (any (cellfun (@(x) (!isscalar (x) || x < 0), varargin)))
+      error ("wblrnd: dimensions must be non-negative integers");
+    endif
+    sz = [varargin{:}];
+  endif
 
-    if (any (size (scale) != 1)
-        && ((length (size (scale)) != length (sz))
-            || any (size (scale) != sz)))
-      error ("wblrnd: SCALE and SHAPE must be scalar or of size SZ");
-    endif
-  elseif (nargin == 2)
-    sz = size(scale);
+  if (!isscalar (scale) && !isequal (size (scale), sz))
+    error ("wblrnd: SCALE and SHAPE must be scalar or of size SZ");
+  endif
+
+  if (isa (scale, "single") || isa (shape, "single"))
+    cls = "single";
   else
-    print_usage ();
+    cls = "double";
   endif
 
   if (isscalar (scale) && isscalar (shape))
-    if (scale > 0 && scale < Inf && shape > 0 && shape < Inf)
-      rnd = scale .* rande(sz) .^ (1./shape);
+    if ((scale > 0) && (scale < Inf) && (shape > 0) && (shape < Inf))
+      rnd = scale * rande (sz) .^ (1/shape);
     else
-      rnd = NaN (sz);
+      rnd = NaN (sz, cls);
     endif
   else
-    rnd = scale .* rande(sz) .^ (1./shape);
-    k = find ((scale <= 0) | (scale == Inf) | ((shape <= 0) & (shape == Inf)));
-    if (any(k))
-      rnd(k) = NaN;
-    endif
+    rnd = scale .* rande (sz) .^ (1./shape);
+
+    k = (scale <= 0) | (scale == Inf) | (shape <= 0) | (shape == Inf);
+    rnd(k) = NaN;
   endif
 
 endfunction
 
+
+%!assert(size (wblrnd (1,2)), [1, 1]);
+%!assert(size (wblrnd (ones(2,1), 2)), [2, 1]);
+%!assert(size (wblrnd (ones(2,2), 2)), [2, 2]);
+%!assert(size (wblrnd (1, 2*ones(2,1))), [2, 1]);
+%!assert(size (wblrnd (1, 2*ones(2,2))), [2, 2]);
+%!assert(size (wblrnd (1, 2, 3)), [3, 3]);
+%!assert(size (wblrnd (1, 2, [4 1])), [4, 1]);
+%!assert(size (wblrnd (1, 2, 4, 1)), [4, 1]);
+
+%% Test class of input preserved
+%!assert(class (wblrnd (1, 2)), "double");
+%!assert(class (wblrnd (single(1), 2)), "single");
+%!assert(class (wblrnd (single([1 1]), 2)), "single");
+%!assert(class (wblrnd (1, single(2))), "single");
+%!assert(class (wblrnd (1, single([2 2]))), "single");
+
+%% Test input validation
+%!error wblrnd ()
+%!error wblrnd (1)
+%!error wblrnd (ones(3),ones(2))
+%!error wblrnd (ones(2),ones(3))
+%!error wblrnd (i, 2)
+%!error wblrnd (2, i)
+%!error wblrnd (1,2, -1)
+%!error wblrnd (1,2, ones(2))
+%!error wblrnd (1, 2, [2 -1 2])
+%!error wblrnd (1,2, 1, ones(2))
+%!error wblrnd (1,2, 1, -1)
+%!error wblrnd (ones(2,2), 2, 3)
+%!error wblrnd (ones(2,2), 2, [3, 2])
+%!error wblrnd (ones(2,2), 2, 2, 3)
+