diff mbox

[v3] Start random dists values testing

Message ID 4D834981.1050202@oracle.com
State New
Headers show

Commit Message

Paolo Carlini March 18, 2011, 12:01 p.m. UTC
Hi,

the below is a start on the long overdue task of checking the values 
produces by the random distributions. For the time being I'm simply 
adapting rather elementary code in GSL, already good enough to enable 
regression tests for libstdc++/48114.

I expect that testing along similar lines the other discrete 
distributions will be pretty straightforward; for the continuous ones 
we'll need an integration routine (I hope something simpler than 
gsl_integration_qags will be enough).

Tested x86_64-linux, committed to mainline.

Paolo.

////////////////////
2011-03-18  Paolo Carlini  <paolo.carlini@oracle.com>

	* testsuite/util/testsuite_random.h: New.
	* testsuite/lib/libstdc++.exp (check_v3_target_c99_math,
	dg-require-c99_math): Add.
	* testsuite/26_numerics/random/bernoulli_distribution/
	operators/values.cc: New.
	* testsuite/26_numerics/random/binomial_distribution/
	operators/values.cc: Likewise.
	* testsuite/26_numerics/random/geometric_distribution/
	operators/values.cc: Likewise.
diff mbox

Patch

Index: testsuite/26_numerics/random/bernoulli_distribution/operators/values.cc
===================================================================
--- testsuite/26_numerics/random/bernoulli_distribution/operators/values.cc	(revision 0)
+++ testsuite/26_numerics/random/bernoulli_distribution/operators/values.cc	(revision 0)
@@ -0,0 +1,50 @@ 
+// { dg-options "-std=gnu++0x" }
+// { dg-require-cstdint "" }
+//
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// 26.5.8.2.1 Class template bernoulli_distribution [rand.dist.bern.bernoulli]
+
+#include <random>
+#include <functional>
+#include <testsuite_random.h>
+
+void test01()
+{
+  using namespace __gnu_test;
+
+  std::mt19937 eng;
+
+  std::bernoulli_distribution bd1(0.25);
+  auto bbd1 = std::bind(bd1, eng);
+  testDiscreteDist(bbd1, [](int n) { return bernoulli_pdf(n, 0.25); } );
+
+  std::bernoulli_distribution bd2(0.5);
+  auto bbd2 = std::bind(bd2, eng);
+  testDiscreteDist(bbd2, [](int n) { return bernoulli_pdf(n, 0.5); } );
+
+  std::bernoulli_distribution bd3(0.75);
+  auto bbd3 = std::bind(bd3, eng);
+  testDiscreteDist(bbd3, [](int n) { return bernoulli_pdf(n, 0.75); } );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
Index: testsuite/26_numerics/random/binomial_distribution/operators/values.cc
===================================================================
--- testsuite/26_numerics/random/binomial_distribution/operators/values.cc	(revision 0)
+++ testsuite/26_numerics/random/binomial_distribution/operators/values.cc	(revision 0)
@@ -0,0 +1,52 @@ 
+// { dg-options "-std=gnu++0x" }
+// { dg-require-cstdint "" }
+// { dg-require-c99_math "" }
+//
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// 26.5.8.2.2 Class template binomial_distribution [rand.dist.bern.bin]
+
+#include <random>
+#include <functional>
+#include <testsuite_random.h>
+
+void test01()
+{
+  using namespace __gnu_test;
+
+  std::mt19937 eng;
+
+  std::binomial_distribution<> bd1(5, 0.3);
+  auto bbd1 = std::bind(bd1, eng);
+  testDiscreteDist(bbd1, [](int n) { return binomial_pdf(n, 0.3, 5); } );
+
+  std::binomial_distribution<> bd2(55, 0.3);
+  auto bbd2 = std::bind(bd2, eng);
+  testDiscreteDist(bbd2, [](int n) { return binomial_pdf(n, 0.3, 55); } );
+
+  // libstdc++/48114
+  std::binomial_distribution<> bd3(10, 0.75);
+  auto bbd3 = std::bind(bd3, eng);
+  testDiscreteDist(bbd3, [](int n) { return binomial_pdf(n, 0.75, 10); } );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
Index: testsuite/26_numerics/random/geometric_distribution/operators/values.cc
===================================================================
--- testsuite/26_numerics/random/geometric_distribution/operators/values.cc	(revision 0)
+++ testsuite/26_numerics/random/geometric_distribution/operators/values.cc	(revision 0)
@@ -0,0 +1,51 @@ 
+// { dg-options "-std=gnu++0x" }
+// { dg-require-cstdint "" }
+//
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// 26.5.8.2.3 Class template geometric_distribution [rand.dist.bern.geom]
+
+#include <random>
+#include <functional>
+#include <testsuite_random.h>
+
+void test01()
+{
+  using namespace __gnu_test;
+
+  std::mt19937 eng;
+
+  std::geometric_distribution<> gd1(0.5);
+  auto bgd1 = std::bind(gd1, eng);
+  testDiscreteDist(bgd1, [](int n) { return geometric_pdf(n, 0.5); } );
+
+  std::geometric_distribution<> gd2(0.75);
+  auto bgd2 = std::bind(gd2, eng);
+  testDiscreteDist(bgd2, [](int n) { return geometric_pdf(n, 0.75); } );
+
+  // libstdc++/48114
+  std::geometric_distribution<> gd3(0.25);
+  auto bgd3 = std::bind(gd3, eng);
+  testDiscreteDist(bgd3, [](int n) { return geometric_pdf(n, 0.25); } );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
Index: testsuite/lib/libstdc++.exp
===================================================================
--- testsuite/lib/libstdc++.exp	(revision 171130)
+++ testsuite/lib/libstdc++.exp	(working copy)
@@ -1,6 +1,7 @@ 
 # libstdc++ "tool init file" for DejaGNU
 
-# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
+# 2009, 2010, 2011
 # Free Software Foundation, Inc.
 #
 # This program is free software; you can redistribute it and/or modify
@@ -1145,12 +1146,70 @@ 
     return $et_cstdint
 }
 
+proc check_v3_target_c99_math { } {
+    global cxxflags
+    global DEFAULT_CXXFLAGS
+    global et_c99_math
+
+    global tool
+
+    if { ![info exists et_c99_math_target_name] } {
+	set et_c99_math_target_name ""
+    }
+
+    # If the target has changed since we set the cached value, clear it.
+    set current_target [current_target_name]
+    if { $current_target != $et_c99_math_target_name } {
+	verbose "check_v3_target_c99_math: `$et_c99_math_target_name'" 2
+	set et_c99_math_target_name $current_target
+	if [info exists et_c99_math] {
+	    verbose "check_v3_target_c99_math: removing cached result" 2
+	    unset et_c99_math
+	}
+    }
+
+    if [info exists et_c99_math] {
+	verbose "check_v3_target_c99_math: using cached result" 2
+    } else {
+	set et_c99_math 0
+
+	# Set up and compile a C++0x test program that depends
+	# on the C99 math facilities to be available.
+	set src c99_math[pid].cc
+	set exe c99_math[pid].exe
+
+	set f [open $src "w"]
+	puts $f "#include <tr1/cmath>"
+	puts $f "int main()"
+	puts $f "#ifdef _GLIBCXX_USE_C99_MATH_TR1"
+	puts $f "{ return 0; }"
+	puts $f "#endif"
+	close $f
+
+	set cxxflags_saved $cxxflags
+	set cxxflags "$cxxflags $DEFAULT_CXXFLAGS -Werror"
+
+	set lines [v3_target_compile $src $exe executable ""]
+	set cxxflags $cxxflags_saved
+	file delete $src
+
+	if [string match "" $lines] {
+	    # No error message, compilation succeeded.
+	    set et_c99_math 1
+	} else {
+	    verbose "check_v3_target_c99_math: compilation failed" 2
+	}
+    }
+    verbose "check_v3_target_c99_math: $et_c99_math" 2
+    return $et_c99_math
+}
+
 proc check_v3_target_atomic_builtins { } {
     global cxxflags
     global DEFAULT_CXXFLAGS
-    global et_cstdint
+    global et_atomic_builtins
 
-    global tool	
+    global tool
 
     if { ![info exists et_atomic_builtins_target_name] } {
 	set et_atomic_builtins_target_name ""
Index: testsuite/lib/dg-options.exp
===================================================================
--- testsuite/lib/dg-options.exp	(revision 171130)
+++ testsuite/lib/dg-options.exp	(working copy)
@@ -1,6 +1,6 @@ 
 # Handlers for additional dg-xxx keywords in tests.
 
-# Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010
+# Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
 # Free Software Foundation, Inc.
 #
 # This program is free software; you can redistribute it and/or modify
@@ -107,6 +107,15 @@ 
     return
 }
 
+proc dg-require-c99_math { args } {
+    if { ![ check_v3_target_c99_math ] } {
+	upvar dg-do-what dg-do-what
+	set dg-do-what [list [lindex ${dg-do-what} 0] "N" "P"]
+	return
+    }
+    return
+}
+
 proc dg-require-atomic-builtins { args } {
     if { ![ check_v3_target_atomic_builtins ] } {
 	upvar dg-do-what dg-do-what
Index: testsuite/util/testsuite_random.h
===================================================================
--- testsuite/util/testsuite_random.h	(revision 0)
+++ testsuite/util/testsuite_random.h	(revision 0)
@@ -0,0 +1,124 @@ 
+// -*- C++ -*-
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License as published by the Free Software
+// Foundation; either version 3, or (at your option) any later
+// version.
+
+// This library is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+/**
+ * @file testsuite_random.h
+ */
+
+#ifndef _GLIBCXX_TESTSUITE_RANDOM_H
+#define _GLIBCXX_TESTSUITE_RANDOM_H
+
+#include <cmath>
+#include <testsuite_hooks.h>
+
+namespace __gnu_test
+{
+  // Adapted for libstdc++ from GNU gsl-1.14/randist/test.c
+  // Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007, 2010
+  // James Theiler, Brian Gough
+  template<unsigned long BINS = 100,
+	   unsigned long N = 100000,
+	   typename Distribution, typename Pdf>
+    void
+    testDiscreteDist(Distribution& f, Pdf pdf)
+    {
+      bool test __attribute__((unused)) = true;
+      double count[BINS], p[BINS];
+
+      for (unsigned long i = 0; i < BINS; i++)
+	count[i] = 0;
+
+      for (unsigned long i = 0; i < N; i++)
+	{
+	  auto r = f();
+	  if (r >= 0 && r < BINS)
+	    count[r]++;
+	}
+
+      for (unsigned long i = 0; i < BINS; i++)
+	p[i] = pdf(i);
+
+      for (unsigned long i = 0; i < BINS; i++)
+	{
+	  bool status_i;
+	  double d = std::abs(count[i] - N * p[i]);
+
+	  if (p[i] != 0)
+	    {
+	      double s = d / std::sqrt(N * p[i]);
+	      status_i = (s > 5) && (d > 1);
+	    }
+	  else
+	    status_i = (count[i] != 0);
+
+	  VERIFY( !status_i );
+	}
+    }
+
+  inline double
+  bernoulli_pdf(int k, double p)
+  {
+    if (k == 0)
+      return 1 - p;
+    else if (k == 1)
+      return p;
+    else
+      return 0;
+  }
+
+#ifdef _GLIBCXX_USE_C99_MATH_TR1
+  inline double
+  binomial_pdf(int k, double p, int n)
+  {
+    if (k < 0 || k > n)
+      return 0;
+    else
+      {
+	double q;
+
+	if (p == 0) 
+	  q = (k == 0) ? 1 : 0;
+	else if (p == 1)
+	  q = (k == n) ? 1 : 0;
+	else
+	  {
+	    double ln_Cnk = (std::lgamma(n + 1) - std::lgamma(k + 1)
+			     - std::lgamma(n - k + 1));
+	    q = ln_Cnk + k * std::log(p) + (n - k) * std::log1p(-p);
+	    q = std::exp(q);
+	  }
+
+	return q;
+      }
+  }
+#endif
+
+  inline double
+  geometric_pdf(int k, double p)
+  {
+    if (k < 0)
+      return 0;
+    else if (k == 0)
+      return p;
+    else
+      return p * std::pow(1 - p, k);
+  }
+} // namespace __gnu_test
+
+#endif // #ifndef _GLIBCXX_TESTSUITE_RANDOM_H