diff mbox

[libstdc++] Add the logistic distribution as an extension

Message ID 53C00510.2000101@verizon.net
State New
Headers show

Commit Message

Ed Smith-Rowland July 11, 2014, 3:38 p.m. UTC
On 07/10/2014 06:16 AM, Paolo Carlini wrote:
> .. I have another comment: are we sure the usual strategy:
>
>       template<typename _UniformRandomNumberGenerator>
>     result_type
>     operator()(_UniformRandomNumberGenerator& __urng)
>     { return this->operator()(__urng, this->_M_param); }
>
> doesn't make sense here too?
>
> Paolo.
>
 >> Look OK to me too, but I would move both operator() out of line

 >> and definitely operator()(_UniformRandomNumberGenerator&, const 
param_type&) of von_mises_distribution.
Ouch - that on was huge huge!

So moved.  The logistic operator() bodies were small looking to me but 
they aren't one or two lines either.  And DRY.

Rebuilt and retested on x86_64-linux.
OK?
2014-07-11  Edward Smith-Rowland  <3dw4rd@verizon.net>

	Add the logistic_distribution as an extension.
	* include/ext/random: Add the logistic_distribution.
	* include/ext/random.tcc: Add the logistic_distribution.
	* testsuite/ext/random/logistic_distribution/cons/parms.cc: New.
	* testsuite/ext/random/logistic_distribution/cons/default.cc: New.
	* testsuite/ext/random/logistic_distribution/requirements/typedefs.cc:
	New.
	* testsuite/ext/random/logistic_distribution/operators/inequal.cc: New.
	* testsuite/ext/random/logistic_distribution/operators/equal.cc: New.
	* testsuite/ext/random/logistic_distribution/operators/serialize.cc:
	New.

Comments

Paolo Carlini July 11, 2014, 3:42 p.m. UTC | #1
Hi,

On 07/11/2014 05:38 PM, Ed Smith-Rowland wrote:
> OK?
Ok, thanks, but please adjust the dates you have on the testcases to the 
date of the actual commit (I suppose today or tomorrow)

Thanks again!
Paolo.
diff mbox

Patch

Index: include/ext/random
===================================================================
--- include/ext/random	(revision 212442)
+++ include/ext/random	(working copy)
@@ -2728,42 +2728,8 @@ 
       template<typename _UniformRandomNumberGenerator>
 	result_type
 	operator()(_UniformRandomNumberGenerator& __urng,
-		   const param_type& __p)
-	{
-	  const result_type __pi
-	    = __gnu_cxx::__math_constants<result_type>::__pi;
-	  std::__detail::_Adaptor<_UniformRandomNumberGenerator, result_type>
-	    __aurng(__urng);
+		   const param_type& __p);
 
-	  result_type __f;
-	  while (1)
-	    {
-	      result_type __rnd = std::cos(__pi * __aurng());
-	      __f = (result_type(1) + __p._M_r * __rnd) / (__p._M_r + __rnd);
-	      result_type __c = __p._M_kappa * (__p._M_r - __f);
-
-	      result_type __rnd2 = __aurng();
-	      if (__c * (result_type(2) - __c) > __rnd2)
-		break;
-	      if (std::log(__c / __rnd2) >= __c - result_type(1))
-		break;
-	    }
-
-	  result_type __res = std::acos(__f);
-#if _GLIBCXX_USE_C99_MATH_TR1
-	  __res = std::copysign(__res, __aurng() - result_type(0.5));
-#else
-	  if (__aurng() < result_type(0.5))
-	    __res = -__res;
-#endif
-	  __res += __p._M_mu;
-	  if (__res > __pi)
-	    __res -= result_type(2) * __pi;
-	  else if (__res < -__pi)
-	    __res += result_type(2) * __pi;
-	  return __res;
-	}
-
       template<typename _ForwardIterator,
 	       typename _UniformRandomNumberGenerator>
 	void
@@ -3106,6 +3072,227 @@ 
 	       const __gnu_cxx::hypergeometric_distribution<_UIntType>& __d2)
     { return !(__d1 == __d2); }
 
+  /**
+   * @brief A logistic continuous distribution for random numbers.
+   *
+   * The formula for the logistic probability density function is
+   * @f[
+   *     p(x|\a,\b) = \frac{e^{(x - a)/b}}{b[1 + e^{(x - a)/b}]^2}
+   * @f]
+   * where @f$b > 0@f$.
+   *
+   * The formula for the logistic probability function is
+   * @f[
+   *     cdf(x|\a,\b) = \frac{e^{(x - a)/b}}{1 + e^{(x - a)/b}}
+   * @f]
+   * where @f$b > 0@f$.
+   *
+   * <table border=1 cellpadding=10 cellspacing=0>
+   * <caption align=top>Distribution Statistics</caption>
+   * <tr><td>Mean</td><td>@f$a@f$</td></tr>
+   * <tr><td>Variance</td><td>@f$b^2\pi^2/3@f$</td></tr>
+   * <tr><td>Range</td><td>@f$[0, \infty)@f$</td></tr>
+   * </table>
+   */
+  template<typename _RealType = double>
+    class
+    logistic_distribution
+    {
+      static_assert(std::is_floating_point<_RealType>::value,
+		    "template argument not a floating point type");
+
+    public:
+      /** The type of the range of the distribution. */
+      typedef _RealType result_type;
+      /** Parameter type. */
+      struct param_type
+      {
+	typedef logistic_distribution<result_type> distribution_type;
+
+	param_type(result_type __a = result_type(0),
+		   result_type __b = result_type(1))
+	: _M_a(__a), _M_b(__b)
+	{
+	  _GLIBCXX_DEBUG_ASSERT(_M_b > result_type(0));
+	}
+
+	result_type
+	a() const
+	{ return _M_a; }
+
+	result_type
+	b() const
+	{ return _M_b; }
+
+	friend bool
+	operator==(const param_type& __p1, const param_type& __p2)
+	{ return __p1._M_a == __p2._M_a
+              && __p1._M_b == __p2._M_b; }
+
+      private:
+	void _M_initialize();
+
+	result_type _M_a;
+	result_type _M_b;
+      };
+
+      /**
+       * @brief Constructors.
+       */
+      explicit
+      logistic_distribution(result_type __a = result_type(0),
+			    result_type __b = result_type(1))
+      : _M_param(__a, __b)
+      { }
+
+      explicit
+      logistic_distribution(const param_type& __p)
+      : _M_param(__p)
+      { }
+
+      /**
+       * @brief Resets the distribution state.
+       */
+      void
+      reset()
+      { }
+
+      /**
+       * @brief Return the parameters of the distribution.
+       */
+      result_type
+      a() const
+      { return _M_param.a(); }
+
+      result_type
+      b() const
+      { return _M_param.b(); }
+
+      /**
+       * @brief Returns the parameter set of the distribution.
+       */
+      param_type
+      param() const
+      { return _M_param; }
+
+      /**
+       * @brief Sets the parameter set of the distribution.
+       * @param __param The new parameter set of the distribution.
+       */
+      void
+      param(const param_type& __param)
+      { _M_param = __param; }
+
+      /**
+       * @brief Returns the greatest lower bound value of the distribution.
+       */
+      result_type
+      min() const
+      { return -std::numeric_limits<result_type>::max(); }
+
+      /**
+       * @brief Returns the least upper bound value of the distribution.
+       */
+      result_type
+      max() const
+      { return std::numeric_limits<result_type>::max(); }
+
+      /**
+       * @brief Generating functions.
+       */
+      template<typename _UniformRandomNumberGenerator>
+	result_type
+	operator()(_UniformRandomNumberGenerator& __urng)
+	{ return this->operator()(__urng, this->_M_param); }
+
+      template<typename _UniformRandomNumberGenerator>
+	result_type
+	operator()(_UniformRandomNumberGenerator&,
+		   const param_type&);
+
+      template<typename _ForwardIterator,
+	       typename _UniformRandomNumberGenerator>
+	void
+	__generate(_ForwardIterator __f, _ForwardIterator __t,
+		   _UniformRandomNumberGenerator& __urng)
+	{ this->__generate(__f, __t, __urng, this->param()); }
+
+      template<typename _ForwardIterator,
+	       typename _UniformRandomNumberGenerator>
+	void
+	__generate(_ForwardIterator __f, _ForwardIterator __t,
+		   _UniformRandomNumberGenerator& __urng,
+		   const param_type& __p)
+	{ this->__generate_impl(__f, __t, __urng, __p); }
+
+      template<typename _UniformRandomNumberGenerator>
+	void
+	__generate(result_type* __f, result_type* __t,
+		   _UniformRandomNumberGenerator& __urng,
+		   const param_type& __p)
+	{ this->__generate_impl(__f, __t, __urng, __p); }
+
+      /**
+       * @brief Return true if two logistic distributions have
+       *        the same parameters and the sequences that would
+       *        be generated are equal.
+       */
+      template<typename _RealType1>
+        friend bool
+        operator==(const logistic_distribution<_RealType1>& __d1,
+		   const logistic_distribution<_RealType1>& __d2)
+        { return __d1.param() == __d2.param(); }
+
+      /**
+       * @brief Inserts a %logistic_distribution random number distribution
+       * @p __x into the output stream @p __os.
+       *
+       * @param __os An output stream.
+       * @param __x  A %logistic_distribution random number distribution.
+       *
+       * @returns The output stream with the state of @p __x inserted or in
+       * an error state.
+       */
+      template<typename _RealType1, typename _CharT, typename _Traits>
+	friend std::basic_ostream<_CharT, _Traits>&
+	operator<<(std::basic_ostream<_CharT, _Traits>&,
+		   const logistic_distribution<_RealType1>&);
+
+      /**
+       * @brief Extracts a %logistic_distribution random number distribution
+       * @p __x from the input stream @p __is.
+       *
+       * @param __is An input stream.
+       * @param __x A %logistic_distribution random number
+       *            generator engine.
+       *
+       * @returns The input stream with @p __x extracted or in an error state.
+       */
+      template<typename _RealType1, typename _CharT, typename _Traits>
+	friend std::basic_istream<_CharT, _Traits>&
+	operator>>(std::basic_istream<_CharT, _Traits>&,
+		   logistic_distribution<_RealType1>&);
+
+    private:
+      template<typename _ForwardIterator,
+	       typename _UniformRandomNumberGenerator>
+	void
+	__generate_impl(_ForwardIterator __f, _ForwardIterator __t,
+			_UniformRandomNumberGenerator& __urng,
+			const param_type& __p);
+
+      param_type _M_param;
+    };
+
+  /**
+   * @brief Return true if two logistic distributions are not equal.
+   */
+  template<typename _RealType1>
+    inline bool
+    operator!=(const logistic_distribution<_RealType1>& __d1,
+	       const logistic_distribution<_RealType1>& __d2)
+    { return !(__d1 == __d2); }
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace __gnu_cxx
 
Index: include/ext/random.tcc
===================================================================
--- include/ext/random.tcc	(revision 212442)
+++ include/ext/random.tcc	(working copy)
@@ -1248,6 +1248,47 @@ 
 
 
   template<typename _RealType>
+    template<typename _UniformRandomNumberGenerator>
+      typename von_mises_distribution<_RealType>::result_type
+      von_mises_distribution<_RealType>::
+      operator()(_UniformRandomNumberGenerator& __urng,
+		 const param_type& __p)
+      {
+	const result_type __pi
+	  = __gnu_cxx::__math_constants<result_type>::__pi;
+	std::__detail::_Adaptor<_UniformRandomNumberGenerator, result_type>
+	  __aurng(__urng);
+
+	result_type __f;
+	while (1)
+	  {
+	    result_type __rnd = std::cos(__pi * __aurng());
+	    __f = (result_type(1) + __p._M_r * __rnd) / (__p._M_r + __rnd);
+	    result_type __c = __p._M_kappa * (__p._M_r - __f);
+
+	    result_type __rnd2 = __aurng();
+	    if (__c * (result_type(2) - __c) > __rnd2)
+	      break;
+	    if (std::log(__c / __rnd2) >= __c - result_type(1))
+	      break;
+	  }
+
+	result_type __res = std::acos(__f);
+#if _GLIBCXX_USE_C99_MATH_TR1
+	__res = std::copysign(__res, __aurng() - result_type(0.5));
+#else
+	if (__aurng() < result_type(0.5))
+	  __res = -__res;
+#endif
+	__res += __p._M_mu;
+	if (__res > __pi)
+	  __res -= result_type(2) * __pi;
+	else if (__res < -__pi)
+	  __res += result_type(2) * __pi;
+	return __res;
+      }
+
+  template<typename _RealType>
     template<typename _OutputIterator,
 	     typename _UniformRandomNumberGenerator>
       void
@@ -1413,6 +1454,91 @@ 
       return __is;
     }
 
+
+  template<typename _RealType>
+    template<typename _UniformRandomNumberGenerator>
+      typename logistic_distribution<_RealType>::result_type
+      logistic_distribution<_RealType>::
+      operator()(_UniformRandomNumberGenerator& __urng,
+		 const param_type& __p)
+      {
+	std::__detail::_Adaptor<_UniformRandomNumberGenerator, result_type>
+	  __aurng(__urng);
+
+	result_type __arg = result_type(1);
+	while (__arg == result_type(1) || __arg == result_type(0))
+	  __arg = __aurng();
+	return __p.a()
+	     + __p.b() * std::log(__arg / (result_type(1) - __arg));
+      }
+
+  template<typename _RealType>
+    template<typename _OutputIterator,
+	     typename _UniformRandomNumberGenerator>
+      void
+      logistic_distribution<_RealType>::
+      __generate_impl(_OutputIterator __f, _OutputIterator __t,
+		      _UniformRandomNumberGenerator& __urng,
+		      const param_type& __p)
+      {
+	__glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator>)
+	std::__detail::_Adaptor<_UniformRandomNumberGenerator, result_type>
+	  __aurng(__urng);
+
+	while (__f != __t)
+	  {
+	    result_type __arg = result_type(1);
+	    while (__arg == result_type(1) || __arg == result_type(0))
+	      __arg = __aurng();
+	    *__f++ = __p.a()
+		   + __p.b() * std::log(__arg / (result_type(1) - __arg));
+	  }
+      }
+
+  template<typename _RealType, typename _CharT, typename _Traits>
+    std::basic_ostream<_CharT, _Traits>&
+    operator<<(std::basic_ostream<_CharT, _Traits>& __os,
+	       const logistic_distribution<_RealType>& __x)
+    {
+      typedef std::basic_ostream<_CharT, _Traits>  __ostream_type;
+      typedef typename __ostream_type::ios_base    __ios_base;
+
+      const typename __ios_base::fmtflags __flags = __os.flags();
+      const _CharT __fill = __os.fill();
+      const std::streamsize __precision = __os.precision();
+      const _CharT __space = __os.widen(' ');
+      __os.flags(__ios_base::scientific | __ios_base::left);
+      __os.fill(__space);
+      __os.precision(std::numeric_limits<_RealType>::max_digits10);
+
+      __os << __x.a() << __space << __x.b();
+
+      __os.flags(__flags);
+      __os.fill(__fill);
+      __os.precision(__precision);
+      return __os;
+    }
+
+  template<typename _RealType, typename _CharT, typename _Traits>
+    std::basic_istream<_CharT, _Traits>&
+    operator>>(std::basic_istream<_CharT, _Traits>& __is,
+	       logistic_distribution<_RealType>& __x)
+    {
+      typedef std::basic_istream<_CharT, _Traits>  __istream_type;
+      typedef typename __istream_type::ios_base    __ios_base;
+
+      const typename __ios_base::fmtflags __flags = __is.flags();
+      __is.flags(__ios_base::dec | __ios_base::skipws);
+
+      _RealType __a, __b;
+      __is >> __a >> __b;
+      __x.param(typename logistic_distribution<_RealType>::
+		param_type(__a, __b));
+
+      __is.flags(__flags);
+      return __is;
+    }
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
Index: testsuite/ext/random/logistic_distribution/cons/parms.cc
===================================================================
--- testsuite/ext/random/logistic_distribution/cons/parms.cc	(revision 0)
+++ testsuite/ext/random/logistic_distribution/cons/parms.cc	(working copy)
@@ -0,0 +1,48 @@ 
+// { dg-options "-std=c++11" }
+// { dg-require-cstdint "" }
+//
+// 2014-06-18  Edward M. Smith-Rowland  <3dw4rd@verizon.net>
+//
+// Copyright (C) 2014 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.4.8.3.* Class template logistic_distribution [rand.dist.ext.logistic]
+// 26.4.2.4 Concept RandomNumberDistribution [rand.concept.dist]
+
+#include <ext/random>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  bool test [[gnu::unused]] = true;
+
+  __gnu_cxx::logistic_distribution<> u(1.5, 3.0);
+  VERIFY( u.a() == 1.5 );
+  VERIFY( u.b() == 3.0 );
+
+  typedef __gnu_cxx::logistic_distribution<>::result_type result_type;
+  VERIFY( u.min() == -std::numeric_limits<result_type>::max() );
+  VERIFY( u.max() == std::numeric_limits<result_type>::max() );
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}
Index: testsuite/ext/random/logistic_distribution/cons/default.cc
===================================================================
--- testsuite/ext/random/logistic_distribution/cons/default.cc	(revision 0)
+++ testsuite/ext/random/logistic_distribution/cons/default.cc	(working copy)
@@ -0,0 +1,48 @@ 
+// { dg-options "-std=c++11" }
+// { dg-require-cstdint "" }
+//
+// 2014-06-18  Edward M. Smith-Rowland  <3dw4rd@verizon.net>
+//
+// Copyright (C) 2014 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.4.8.3.* Class template logistic_distribution [rand.dist.ext.logistic]
+// 26.4.2.4 Concept RandomNumberDistribution [rand.concept.dist]
+
+#include <ext/random>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  bool test [[gnu::unused]] = true;
+
+  __gnu_cxx::logistic_distribution<> u;
+  VERIFY( u.a() == 0.0 );
+  VERIFY( u.b() == 1.0 );
+
+  typedef __gnu_cxx::logistic_distribution<>::result_type result_type;
+  VERIFY( u.min() == -std::numeric_limits<result_type>::max() );
+  VERIFY( u.max() == std::numeric_limits<result_type>::max() );
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}
Index: testsuite/ext/random/logistic_distribution/requirements/typedefs.cc
===================================================================
--- testsuite/ext/random/logistic_distribution/requirements/typedefs.cc	(revision 0)
+++ testsuite/ext/random/logistic_distribution/requirements/typedefs.cc	(working copy)
@@ -0,0 +1,36 @@ 
+// { dg-do compile }
+// { dg-options "-std=c++11" }
+// { dg-require-cstdint "" }
+//
+// 2014-06-18  Edward M. Smith-Rowland <3dw4rd@verizon.net>
+//
+// Copyright (C) 2014 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.4.8.3.* Class template logistic_distribution [rand.dist.ext.logistic]
+// 26.4.2.4 Concept RandomNumberDistribution [rand.concept.dist]
+
+#include <ext/random>
+
+void
+test01()
+{
+  typedef __gnu_cxx::logistic_distribution<double> test_type;
+
+  typedef test_type::result_type result_type;
+  typedef test_type::param_type param_type;
+}
Index: testsuite/ext/random/logistic_distribution/operators/inequal.cc
===================================================================
--- testsuite/ext/random/logistic_distribution/operators/inequal.cc	(revision 0)
+++ testsuite/ext/random/logistic_distribution/operators/inequal.cc	(working copy)
@@ -0,0 +1,44 @@ 
+// { dg-options "-std=c++11" }
+// { dg-require-cstdint "" }
+//
+// 2014-06-18  Edward M. Smith-Rowland  <3dw4rd@verizon.net>
+//
+// Copyright (C) 2014 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.4.5 Class template logistic_distribution [rand.dist.ext.logistic]
+
+#include <ext/random>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  bool test [[gnu::unused]] = true;
+
+  __gnu_cxx::logistic_distribution<double> u(2.0, 3.0), v, w;
+
+  VERIFY( u != v );
+  VERIFY( !(v != w) );
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}
Index: testsuite/ext/random/logistic_distribution/operators/equal.cc
===================================================================
--- testsuite/ext/random/logistic_distribution/operators/equal.cc	(revision 0)
+++ testsuite/ext/random/logistic_distribution/operators/equal.cc	(working copy)
@@ -0,0 +1,44 @@ 
+// { dg-options "-std=c++11" }
+// { dg-require-cstdint "" }
+//
+// 2014-06-18  Edward M. Smith-Rowland  <3dw4rd@verizon.net>
+//
+// Copyright (C) 2014 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.4.5 Class template logistic_distribution [rand.dist.ext.logistic]
+
+#include <ext/random>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  bool test [[gnu::unused]] = true;
+
+  __gnu_cxx::logistic_distribution<double> u(2.0, 3.0), v, w;
+
+  VERIFY( v == w );
+  VERIFY( !(u == v) );
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}
Index: testsuite/ext/random/logistic_distribution/operators/serialize.cc
===================================================================
--- testsuite/ext/random/logistic_distribution/operators/serialize.cc	(revision 0)
+++ testsuite/ext/random/logistic_distribution/operators/serialize.cc	(working copy)
@@ -0,0 +1,51 @@ 
+// { dg-options "-std=c++11" }
+// { dg-require-cstdint "" }
+//
+// 2014-06-18  Edward M. Smith-Rowland  <3dw4rd@verizon.net>
+//
+// Copyright (C) 2014 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.4.8.3.* Class template logistic_distribution [rand.dist.ext.logistic]
+// 26.4.2.4 Concept RandomNumberDistribution [rand.concept.dist]
+
+#include <ext/random>
+#include <sstream>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  bool test [[gnu::unused]] = true;
+
+  std::stringstream str;
+  __gnu_cxx::logistic_distribution<double> u(1.5, 3.0), v;
+  std::minstd_rand0 rng;
+
+  u(rng); // advance
+  str << u;
+
+  str >> v;
+  VERIFY( u == v );
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}