From patchwork Fri Mar 18 12:01:05 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Carlini X-Patchwork-Id: 87519 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 4B67EB6EFE for ; Fri, 18 Mar 2011 23:01:34 +1100 (EST) Received: (qmail 6774 invoked by alias); 18 Mar 2011 12:01:28 -0000 Received: (qmail 6746 invoked by uid 22791); 18 Mar 2011 12:01:24 -0000 X-SWARE-Spam-Status: No, hits=-1.7 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_NONE, TW_BG, TW_CX, TW_XX X-Spam-Check-By: sourceware.org Received: from smtp206.alice.it (HELO smtp206.alice.it) (82.57.200.102) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 18 Mar 2011 12:01:11 +0000 Received: from [192.168.1.4] (79.52.240.105) by smtp206.alice.it (8.5.124.08) id 4D49918D03C5779A; Fri, 18 Mar 2011 13:01:06 +0100 Message-ID: <4D834981.1050202@oracle.com> Date: Fri, 18 Mar 2011 13:01:05 +0100 From: Paolo Carlini User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.14) Gecko/20110221 SUSE/3.1.8 Thunderbird/3.1.8 MIME-Version: 1.0 To: "gcc-patches@gcc.gnu.org" CC: libstdc++ Subject: [v3] Start random dists values testing X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org 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 * 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. 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 +// . + +// 26.5.8.2.1 Class template bernoulli_distribution [rand.dist.bern.bernoulli] + +#include +#include +#include + +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 +// . + +// 26.5.8.2.2 Class template binomial_distribution [rand.dist.bern.bin] + +#include +#include +#include + +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 +// . + +// 26.5.8.2.3 Class template geometric_distribution [rand.dist.bern.geom] + +#include +#include +#include + +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 " + 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 +// . + +/** + * @file testsuite_random.h + */ + +#ifndef _GLIBCXX_TESTSUITE_RANDOM_H +#define _GLIBCXX_TESTSUITE_RANDOM_H + +#include +#include + +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 + 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