summaryrefslogtreecommitdiff
path: root/vendor/CppQuickCheck-2018-03-28/include/cppqc/Arbitrary.h
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/CppQuickCheck-2018-03-28/include/cppqc/Arbitrary.h')
-rw-r--r--vendor/CppQuickCheck-2018-03-28/include/cppqc/Arbitrary.h446
1 files changed, 446 insertions, 0 deletions
diff --git a/vendor/CppQuickCheck-2018-03-28/include/cppqc/Arbitrary.h b/vendor/CppQuickCheck-2018-03-28/include/cppqc/Arbitrary.h
new file mode 100644
index 00000000..ecfc56c1
--- /dev/null
+++ b/vendor/CppQuickCheck-2018-03-28/include/cppqc/Arbitrary.h
@@ -0,0 +1,446 @@
+/*
+ * Copyright (c) 2010, Gregory Rogers All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CPPQC_ARBITRARY_H
+#define CPPQC_ARBITRARY_H
+
+#include "Generator.h"
+
+#include <limits>
+
+#include <boost/random/uniform_int.hpp>
+#include <boost/random/uniform_smallint.hpp>
+#include <boost/random/uniform_real.hpp>
+#include <boost/random/uniform_01.hpp>
+#include <boost/random/poisson_distribution.hpp>
+#include <boost/random/variate_generator.hpp>
+
+namespace cppqc {
+
+// default generators
+
+template<class Integral>
+Integral arbitrarySizedIntegral(RngEngine &rng, std::size_t size)
+{
+ boost::uniform_int<Integral> dist(std::numeric_limits<Integral>::is_signed ?
+ -Integral(size) : Integral(size),
+ Integral(size));
+ return dist(rng);
+}
+
+template<class Integral>
+Integral arbitraryBoundedIntegral(RngEngine &rng, std::size_t /*size*/)
+{
+ boost::uniform_int<Integral> dist(std::numeric_limits<Integral>::min(),
+ std::numeric_limits<Integral>::max());
+ return dist(rng);
+}
+
+template<class Integral>
+Integral arbitrarySizedBoundedIntegral(RngEngine &rng, std::size_t size)
+{
+ boost::poisson_distribution<Integral> dist(size == 0 ? 1 : size);
+ boost::variate_generator<RngEngine&, boost::uniform_01<> > gen(rng, boost::uniform_01<>());
+ Integral r = dist(gen);
+ if (std::numeric_limits<Integral>::is_signed) {
+ if (boost::uniform_smallint<int>(0, 1)(rng))
+ r = -r;
+ }
+ return r;
+}
+
+template<class Real>
+Real arbitrarySizedReal(RngEngine &rng, std::size_t size)
+{
+ boost::uniform_real<Real> dist(-Real(size + 1.0), Real(size + 1.0));
+ return dist(rng);
+}
+
+// default shrinkers
+
+template<class T>
+std::vector<T> shrinkNothing(const T &)
+{
+ return std::vector<T>();
+}
+
+template<class Integral>
+std::vector<Integral> shrinkIntegral(Integral x)
+{
+ std::vector<Integral> ret;
+ if (std::numeric_limits<Integral>::is_signed && x < 0) {
+ if (x == std::numeric_limits<Integral>::min()) {
+ ret.push_back(std::numeric_limits<Integral>::max());
+ } else {
+ assert(-x > 0);
+ ret.push_back(-x);
+ }
+ }
+
+ for (Integral n = x; n != 0; n /= 2)
+ ret.push_back(x - n);
+ return ret;
+}
+
+template<class Real>
+std::vector<Real> shrinkReal(Real x)
+{
+ std::vector<Real> ret;
+ if (x == 0)
+ return ret;
+ if (x < 0)
+ ret.push_back(-x);
+ ret.push_back(Real(0));
+
+ if (std::isnan(x) && std::abs(x) >= 2) {
+ if (std::abs(x) < 1e100) {
+ ret.push_back(x / Real(2));
+ } else {
+ // special case: reduce faster if the numbers are huge
+ // (Note: Maybe there is a better heuristic. Looks quite crude.)
+ ret.push_back(x / Real(1e20));
+ }
+ }
+ return ret;
+}
+
+
+template<class T>
+struct Arbitrary
+{
+ typedef boost::function<T (RngEngine &, std::size_t)> unGenType;
+ typedef boost::function<std::vector<T> (T)> shrinkType;
+
+ static const unGenType unGen;
+ static const shrinkType shrink;
+};
+
+/*
+ * specialize ArbitraryImpl and implement the members:
+ * static const Arbitrary<T>::unGenType unGen;
+ * static const Arbitrary<T>::shrinkType shrink;
+ */
+template<class T>
+struct ArbitraryImpl
+{
+ // no default implementation - users must specialize ArbitraryImpl
+ // and give an implementation of unGen and shrink. If they do not
+ // and they try to use Arbitrary<TheirClass>, a compile error will result.
+};
+
+// Note: The call is wrapped in a function to avoid issues
+// with static ordering when ArbitraryImpl is defined
+// in another compilation unit. Do not simplify it
+// by replacing it with an assignment.
+template<class T>
+const typename Arbitrary<T>::unGenType Arbitrary<T>::unGen = [](RngEngine &rng,
+ std::size_t size) {
+ return ArbitraryImpl<T>::unGen(rng, size);
+};
+
+// (function call is needed: see above)
+template<class T>
+const typename Arbitrary<T>::shrinkType Arbitrary<T>::shrink = [](const T &v) {
+ return ArbitraryImpl<T>::shrink(v);
+};
+
+// included specializations
+
+inline bool arbitraryBool(RngEngine &rng, std::size_t /*size*/)
+{
+ if (boost::uniform_smallint<int>(0, 1)(rng))
+ return true;
+ return false;
+}
+inline std::vector<bool> shrinkBool(bool x)
+{
+ std::vector<bool> ret;
+ if (x) ret.push_back(false);
+ return ret;
+}
+template<>
+struct ArbitraryImpl<bool>
+{
+ static const Arbitrary<bool>::unGenType unGen;
+ static const Arbitrary<bool>::shrinkType shrink;
+};
+
+template<>
+struct ArbitraryImpl<signed char>
+{
+ static const Arbitrary<signed char>::unGenType unGen;
+ static const Arbitrary<signed char>::shrinkType shrink;
+};
+
+template<>
+struct ArbitraryImpl<unsigned char>
+{
+ static const Arbitrary<unsigned char>::unGenType unGen;
+ static const Arbitrary<unsigned char>::shrinkType shrink;
+};
+
+template<>
+struct ArbitraryImpl<signed short>
+{
+ static const Arbitrary<signed short>::unGenType unGen;
+ static const Arbitrary<signed short>::shrinkType shrink;
+};
+
+template<>
+struct ArbitraryImpl<unsigned short>
+{
+ static const Arbitrary<unsigned short>::unGenType unGen;
+ static const Arbitrary<unsigned short>::shrinkType shrink;
+};
+
+template<>
+struct ArbitraryImpl<signed int>
+{
+ static const Arbitrary<signed int>::unGenType unGen;
+ static const Arbitrary<signed int>::shrinkType shrink;
+};
+
+template<>
+struct ArbitraryImpl<unsigned int>
+{
+ static const Arbitrary<unsigned int>::unGenType unGen;
+ static const Arbitrary<unsigned int>::shrinkType shrink;
+};
+
+template<>
+struct ArbitraryImpl<signed long>
+{
+ static const Arbitrary<signed long>::unGenType unGen;
+ static const Arbitrary<signed long>::shrinkType shrink;
+};
+
+template<>
+struct ArbitraryImpl<unsigned long>
+{
+ static const Arbitrary<unsigned long>::unGenType unGen;
+ static const Arbitrary<unsigned long>::shrinkType shrink;
+};
+
+template<>
+struct ArbitraryImpl<signed long long>
+{
+ static const Arbitrary<signed long long>::unGenType unGen;
+ static const Arbitrary<signed long long>::shrinkType shrink;
+};
+
+template<>
+struct ArbitraryImpl<unsigned long long>
+{
+ static const Arbitrary<unsigned long long>::unGenType unGen;
+ static const Arbitrary<unsigned long long>::shrinkType shrink;
+};
+
+template<>
+struct ArbitraryImpl<float>
+{
+ static const Arbitrary<float>::unGenType unGen;
+ static const Arbitrary<float>::shrinkType shrink;
+};
+
+template<>
+struct ArbitraryImpl<double>
+{
+ static const Arbitrary<double>::unGenType unGen;
+ static const Arbitrary<double>::shrinkType shrink;
+};
+
+template<>
+struct ArbitraryImpl<long double>
+{
+ static const Arbitrary<long double>::unGenType unGen;
+ static const Arbitrary<long double>::shrinkType shrink;
+};
+
+inline char arbitraryChar(RngEngine &rng, std::size_t)
+{
+ boost::uniform_int<char> dist(0x20, 0x7f);
+ return dist(rng);
+}
+inline std::vector<char> shrinkChar(char c)
+{
+ const char possShrinks[] = {'a', 'b', 'c', 'A', 'B', 'C', '1', '2', '3',
+ ' ', '\n', '\0'};
+ std::vector<char> ret;
+ for (auto & possShrink : possShrinks) {
+ if (possShrink < c)
+ ret.push_back(possShrink);
+ }
+ if (isupper(c) &&
+ std::find(possShrinks, possShrinks + sizeof(possShrinks),
+ tolower(c)) != possShrinks + sizeof(possShrinks))
+ ret.push_back(tolower(c));
+ return ret;
+}
+template<>
+struct ArbitraryImpl<char>
+{
+ static const Arbitrary<char>::unGenType unGen;
+ static const Arbitrary<char>::shrinkType shrink;
+};
+
+template<>
+struct ArbitraryImpl<wchar_t>
+{
+ static const Arbitrary<wchar_t>::unGenType unGen;
+ static const Arbitrary<wchar_t>::shrinkType shrink;
+};
+
+template<class String>
+String arbitraryString(RngEngine &rng, std::size_t size)
+{
+ boost::uniform_int<std::size_t> dist(0, size);
+ std::size_t n = dist(rng);
+ String ret;
+ ret.reserve(n);
+ while (n-- > 0)
+ ret.push_back(Arbitrary<typename String::value_type>::unGen(rng, size));
+ return ret;
+}
+template<class String>
+std::vector<String> shrinkString(const String &x)
+{
+ std::vector<String> ret;
+ ret.reserve(x.size());
+ for (auto it = x.begin(); it != x.end(); ++it) {
+ ret.push_back(String());
+ ret.back().reserve(x.size() - 1);
+ ret.back().insert(ret.back().end(), x.begin(), it);
+ ret.back().insert(ret.back().end(), it + 1, x.end());
+ }
+ return ret;
+}
+template<class CharT, class Traits, class Alloc>
+struct ArbitraryImpl<std::basic_string<CharT, Traits, Alloc> >
+{
+ static const typename
+ Arbitrary<std::basic_string<CharT, Traits, Alloc> >::unGenType unGen;
+ static const typename
+ Arbitrary<std::basic_string<CharT, Traits, Alloc> >::shrinkType shrink;
+};
+template<class CharT, class Traits, class Alloc>
+const typename Arbitrary<std::basic_string<CharT, Traits, Alloc> >::unGenType
+ArbitraryImpl<std::basic_string<CharT, Traits, Alloc> >::unGen =
+arbitraryString<std::basic_string<CharT, Traits, Alloc> >;
+template<class CharT, class Traits, class Alloc>
+const typename Arbitrary<std::basic_string<CharT, Traits, Alloc> >::shrinkType
+ArbitraryImpl<std::basic_string<CharT, Traits, Alloc> >::shrink =
+shrinkString<std::basic_string<CharT, Traits, Alloc> >;
+
+template<class PairType>
+PairType arbitraryPair(RngEngine &rng, std::size_t size)
+{
+ return PairType(Arbitrary<typename PairType::first_type>::unGen(rng, size),
+ Arbitrary<typename PairType::second_type>::unGen(rng, size));
+}
+template<class PairType>
+std::vector<PairType> shrinkPair(const PairType &x)
+{
+ typedef typename PairType::first_type FirstType;
+ typedef typename PairType::second_type SecondType;
+ std::vector<FirstType> shrinks1 = Arbitrary<FirstType>::shrink(x.first);
+ std::vector<SecondType> shrinks2 = Arbitrary<SecondType>::shrink(x.second);
+ std::vector<PairType> ret;
+ ret.reserve(shrinks1.size() + shrinks2.size());
+ for (auto it = shrinks1.begin(); it != shrinks1.end(); ++it) {
+ ret.push_back(PairType(*it, x.second));
+ }
+ for (auto it = shrinks2.begin(); it != shrinks2.end(); ++it) {
+ ret.push_back(PairType(x.first, *it));
+ }
+ return ret;
+}
+template<class T1, class T2>
+struct ArbitraryImpl<std::pair<T1, T2> >
+{
+ static const typename Arbitrary<std::pair<T1, T2> >::unGenType unGen;
+ static const typename Arbitrary<std::pair<T1, T2> >::shrinkType shrink;
+};
+template<class T1, class T2>
+const typename Arbitrary<std::pair<T1, T2> >::unGenType
+ArbitraryImpl<std::pair<T1, T2> >::unGen = arbitraryPair<std::pair<T1, T2> >;
+template<class T1, class T2>
+const typename Arbitrary<std::pair<T1, T2> >::shrinkType
+ArbitraryImpl<std::pair<T1, T2> >::shrink = shrinkPair<std::pair<T1, T2> >;
+
+template<typename T>
+struct ArbitraryImpl<std::vector<T>>
+{
+ static const typename Arbitrary<std::vector<T>>::unGenType unGen;
+ static const typename Arbitrary<std::vector<T>>::shrinkType shrink;
+};
+
+template <typename T>
+const typename Arbitrary<std::vector<T>>::unGenType
+ ArbitraryImpl<std::vector<T>>::unGen = [](RngEngine &rng,
+ std::size_t size) {
+ const auto& vectorGenerator = listOf<T>();
+ return vectorGenerator.unGen(rng, size);
+};
+
+template <typename T>
+const typename Arbitrary<std::vector<T>>::shrinkType
+ ArbitraryImpl<std::vector<T>>::shrink = [](const std::vector<T> &v) {
+
+ const auto& vectorGenerator = listOf<T>();
+ return vectorGenerator.shrink(v);
+};
+
+
+template<typename T, std::size_t N>
+struct ArbitraryImpl<std::array<T, N>>
+{
+ static const typename Arbitrary<std::array<T, N>>::unGenType unGen;
+ static const typename Arbitrary<std::array<T, N>>::shrinkType shrink;
+};
+
+/// Note: N is the fixed size of the array.
+/// It differs from the "size" param in the "unGen" function:
+///
+/// If "size" is increased, the output array will still contain
+/// N elements, but each element will, in general, be more complex.
+template <typename T, std::size_t N>
+const typename Arbitrary<std::array<T, N>>::unGenType
+ ArbitraryImpl<std::array<T, N>>::unGen = [](RngEngine &rng,
+ std::size_t size) {
+ const auto& arrayGenerator = arrayOf<T, N>();
+ return arrayGenerator.unGen(rng, size);
+};
+
+template <typename T, std::size_t N>
+const typename Arbitrary<std::array<T, N>>::shrinkType
+ ArbitraryImpl<std::array<T, N>>::shrink = [](const std::array<T, N> &arr) {
+
+ const auto& arrayGenerator = arrayOf<T, N>();
+ return arrayGenerator.shrink(arr);
+};
+
+}
+
+#endif