[PATCH ] PR libstdc++/60037 - SIGFPE in std::generate_canonicalunsigned int...

2014-07-29 Thread Ed Smith-Rowland
As discussed in the audit trail both _Adaptor and generate_canonical are 
both meant to use floating point values.  Both are here given 
static_asserts to that effect.

This would have prevented this error and might help future users.

The main issue is the use of value_type in _Adaptor and thus in 
generate_canonical in hypergeometric_distribution::operator().  This 
distribution is a discreet distribution and thus value_type is an 
unsigned integer which caused overflow in generate_canonical.  In 
keeping with practice in all other discreet distributions a double type 
will now be used in _Adaptor.


Someday, it might be beneficial to discuss an _IntegralAdaptor and a 
corresponding __generate_canonical for use in our discreet distributions 
but I want to close this bug with this patch.


Built and tested on x86_64-linux.

OK?


2014-07-29  Ed Smith-Rowland  3dw...@verizon.net

* include/bits/random.h (_Adaptor): static_assert for non floating-point
result type.
* include/bits/random.tcc (generate_canonical): Ditto.
* include/ext/random.tcc (hypergeometric_distribution::operator()):
Use double as a rng result type.
* testsuite/26_numerics/random/pr60037-neg.cc: New.
* testsuite/ext/random/hypergeometric_distribution/pr60037.cc: New.

Index: include/bits/random.h
===
--- include/bits/random.h   (revision 213145)
+++ include/bits/random.h   (working copy)
@@ -164,6 +164,8 @@
 templatetypename _Engine, typename _DInputType
   struct _Adaptor
   {
+   static_assert(std::is_floating_point_DInputType::value,
+ template argument not a floating point type);
 
   public:
_Adaptor(_Engine __g)
Index: include/bits/random.tcc
===
--- include/bits/random.tcc (revision 213145)
+++ include/bits/random.tcc (working copy)
@@ -3463,6 +3463,9 @@
 _RealType
 generate_canonical(_UniformRandomNumberGenerator __urng)
 {
+  static_assert(std::is_floating_point_RealType::value,
+   template argument not a floating point type);
+
   const size_t __b
= std::min(static_castsize_t(std::numeric_limits_RealType::digits),
__bits);
Index: include/ext/random.tcc
===
--- include/ext/random.tcc  (revision 213145)
+++ include/ext/random.tcc  (working copy)
@@ -1355,7 +1355,7 @@
   operator()(_UniformRandomNumberGenerator __urng,
 const param_type __param)
   {
-   std::__detail::_Adaptor_UniformRandomNumberGenerator, result_type
+   std::__detail::_Adaptor_UniformRandomNumberGenerator, double
  __aurng(__urng);
 
result_type __a = __param.successful_size();
Index: testsuite/26_numerics/random/pr60037-neg.cc
===
--- testsuite/26_numerics/random/pr60037-neg.cc (revision 0)
+++ testsuite/26_numerics/random/pr60037-neg.cc (working copy)
@@ -0,0 +1,9 @@
+
+#include random
+
+std::mt19937 urng;
+
+std::__detail::_Adaptorstd::mt19937, unsigned long aurng(urng); // { 
dg-error template argument not a floating point type }
+
+auto x = std::generate_canonicalstd::size_t,
+   std::numeric_limitsstd::size_t::digits(urng); // { 
dg-error template argument not a floating point type }
Index: testsuite/ext/random/hypergeometric_distribution/pr60037.cc
===
--- testsuite/ext/random/hypergeometric_distribution/pr60037.cc (revision 0)
+++ testsuite/ext/random/hypergeometric_distribution/pr60037.cc (working copy)
@@ -0,0 +1,24 @@
+// { dg-options -std=gnu++11 }
+// { dg-require-cstdint  }
+// { dg-require-cmath  }
+// { dg-options -O0 }
+
+#include ext/random
+#include functional
+
+void
+hyperplot(unsigned int N, unsigned int K, unsigned int n)
+{
+  std::mt19937 re; // the default engine
+  __gnu_cxx::hypergeometric_distribution hd(N, K, n);
+  auto gen = std::bind(hd, re);
+  gen();
+}
+
+int
+main()
+{
+  hyperplot(15, 3, 2);
+  hyperplot(500, 50, 30);
+  hyperplot(100, 20, 5);
+}


Re: [PATCH ] PR libstdc++/60037 - SIGFPE in std::generate_canonicalunsigned int...

2014-07-29 Thread Jonathan Wakely

On 29/07/14 04:11 -0400, Ed Smith-Rowland wrote:
As discussed in the audit trail both _Adaptor and generate_canonical 
are both meant to use floating point values.  Both are here given 
static_asserts to that effect.

This would have prevented this error and might help future users.

The main issue is the use of value_type in _Adaptor and thus in 
generate_canonical in hypergeometric_distribution::operator().  This 
distribution is a discreet distribution and thus value_type is an 
unsigned integer which caused overflow in generate_canonical.  In 
keeping with practice in all other discreet distributions a double 
type will now be used in _Adaptor.


Someday, it might be beneficial to discuss an _IntegralAdaptor and a 
corresponding __generate_canonical for use in our discreet 
distributions but I want to close this bug with this patch.


Makes sense, thanks for the fix.


Built and tested on x86_64-linux.

OK?


One question ...


Index: testsuite/ext/random/hypergeometric_distribution/pr60037.cc
===
--- testsuite/ext/random/hypergeometric_distribution/pr60037.cc (revision 0)
+++ testsuite/ext/random/hypergeometric_distribution/pr60037.cc (working copy)
@@ -0,0 +1,24 @@
+// { dg-options -std=gnu++11 }
+// { dg-require-cstdint  }
+// { dg-require-cmath  }
+// { dg-options -O0 }


Did you mean to have two separate dg-options directives here?

OK to commit, after either combining them into one or removing the
second one.


Re: [PATCH ] PR libstdc++/60037 - SIGFPE in std::generate_canonicalunsigned int...

2014-07-29 Thread Ed Smith-Rowland

On 07/29/2014 04:29 AM, Jonathan Wakely wrote:

On 29/07/14 04:11 -0400, Ed Smith-Rowland wrote:
As discussed in the audit trail both _Adaptor and generate_canonical 
are both meant to use floating point values.  Both are here given 
static_asserts to that effect.

This would have prevented this error and might help future users.

The main issue is the use of value_type in _Adaptor and thus in 
generate_canonical in hypergeometric_distribution::operator(). This 
distribution is a discreet distribution and thus value_type is an 
unsigned integer which caused overflow in generate_canonical.  In 
keeping with practice in all other discreet distributions a double 
type will now be used in _Adaptor.


Someday, it might be beneficial to discuss an _IntegralAdaptor and a 
corresponding __generate_canonical for use in our discreet 
distributions but I want to close this bug with this patch.


Makes sense, thanks for the fix.


Built and tested on x86_64-linux.

OK?


One question ...


Index: testsuite/ext/random/hypergeometric_distribution/pr60037.cc
===
--- testsuite/ext/random/hypergeometric_distribution/pr60037.cc 
(revision 0)
+++ testsuite/ext/random/hypergeometric_distribution/pr60037.cc 
(working copy)

@@ -0,0 +1,24 @@
+// { dg-options -std=gnu++11 }
+// { dg-require-cstdint  }
+// { dg-require-cmath  }
+// { dg-options -O0 }


Did you mean to have two separate dg-options directives here?

OK to commit, after either combining them into one or removing the
second one.


Committed (with small changes to test cases).
Attached new CLand patch.

2014-07-29  Ed Smith-Rowland  3dw...@verizon.net

PR libstdc++/60037 - SIGFPE in std::generate_canonicalunsigned int...
* include/bits/random.h (_Adaptor): static_assert for non floating-point
result type.
* include/bits/random.tcc (generate_canonical): Ditto.
* include/ext/random.tcc (hypergeometric_distribution::operator()):
Use double as a rng result type.
* testsuite/26_numerics/random/pr60037-neg.cc: New.
* testsuite/ext/random/hypergeometric_distribution/pr60037.cc: New.

Index: include/bits/random.h
===
--- include/bits/random.h   (revision 213145)
+++ include/bits/random.h   (working copy)
@@ -164,6 +164,8 @@
 templatetypename _Engine, typename _DInputType
   struct _Adaptor
   {
+   static_assert(std::is_floating_point_DInputType::value,
+ template argument not a floating point type);
 
   public:
_Adaptor(_Engine __g)
Index: include/bits/random.tcc
===
--- include/bits/random.tcc (revision 213145)
+++ include/bits/random.tcc (working copy)
@@ -3463,6 +3463,9 @@
 _RealType
 generate_canonical(_UniformRandomNumberGenerator __urng)
 {
+  static_assert(std::is_floating_point_RealType::value,
+   template argument not a floating point type);
+
   const size_t __b
= std::min(static_castsize_t(std::numeric_limits_RealType::digits),
__bits);
Index: include/ext/random.tcc
===
--- include/ext/random.tcc  (revision 213145)
+++ include/ext/random.tcc  (working copy)
@@ -1355,7 +1355,7 @@
   operator()(_UniformRandomNumberGenerator __urng,
 const param_type __param)
   {
-   std::__detail::_Adaptor_UniformRandomNumberGenerator, result_type
+   std::__detail::_Adaptor_UniformRandomNumberGenerator, double
  __aurng(__urng);
 
result_type __a = __param.successful_size();
Index: testsuite/26_numerics/random/pr60037-neg.cc
===
--- testsuite/26_numerics/random/pr60037-neg.cc (revision 0)
+++ testsuite/26_numerics/random/pr60037-neg.cc (working copy)
@@ -0,0 +1,15 @@
+// { dg-do compile }
+// { dg-options -std=gnu++11 }
+
+#include random
+
+std::mt19937 urng;
+
+std::__detail::_Adaptorstd::mt19937, unsigned long aurng(urng);
+
+auto x = std::generate_canonicalstd::size_t,
+   std::numeric_limitsstd::size_t::digits(urng);
+
+// { dg-error static assertion failed: template argument not a floating point 
type  { target *-*-* } 167 }
+
+// { dg-error static assertion failed: template argument not a floating point 
type  { target *-*-* } 3466 }
Index: testsuite/ext/random/hypergeometric_distribution/pr60037.cc
===
--- testsuite/ext/random/hypergeometric_distribution/pr60037.cc (revision 0)
+++ testsuite/ext/random/hypergeometric_distribution/pr60037.cc (working copy)
@@ -0,0 +1,23 @@
+// { dg-options -std=gnu++11 -O0 }
+// { dg-require-cstdint  }
+// { dg-require-cmath  }
+
+#include ext/random
+#include functional
+
+void