Hegel 0.3.5
Property-based testing for C++
Loading...
Searching...
No Matches
numeric.h
1#pragma once
2
3#include <limits>
4
5#include "hegel/core.h"
6
7namespace hegel::generators {
8
9 // =============================================================================
10 // Parameter structs
11 // =============================================================================
12
17 template <typename T> struct IntegersParams {
18 std::optional<T>
20 std::optional<T>
22 };
23
28 template <typename T> struct FloatsParams {
29 std::optional<T> min_value;
30 std::optional<T> max_value;
32 false;
34 false;
35 std::optional<bool>
37 std::optional<bool>
39 };
40
42 // Concrete IGenerator<T> subclass produced by integers().
43 template <typename T>
44 requires std::is_integral_v<T>
45 class IntegerGenerator : public IGenerator<T> {
46 public:
47 explicit IntegerGenerator(IntegersParams<T> params = {})
48 : params_(std::move(params)) {
49 T min_val =
50 params_.min_value.value_or(std::numeric_limits<T>::min());
51 T max_val =
52 params_.max_value.value_or(std::numeric_limits<T>::max());
53 if (min_val > max_val) {
54 throw std::invalid_argument(
55 "Cannot have max_value < min_value");
56 }
57 }
58
59 std::optional<BasicGenerator<T>> as_basic() const override {
60 T min_val =
61 params_.min_value.value_or(std::numeric_limits<T>::min());
62 T max_val =
63 params_.max_value.value_or(std::numeric_limits<T>::max());
64 return BasicGenerator<T>{{{"type", "integer"},
65 {"min_value", min_val},
66 {"max_value", max_val}},
67 &default_parse_raw<T>};
68 }
69
70 private:
71 IntegersParams<T> params_;
72 };
73
74 // Concrete IGenerator<T> subclass produced by floats().
75 template <typename T>
76 requires std::is_floating_point_v<T>
77 class FloatGenerator : public IGenerator<T> {
78 public:
79 explicit FloatGenerator(FloatsParams<T> params = {})
80 : params_(std::move(params)) {
81 bool has_min = params_.min_value.has_value();
82 bool has_max = params_.max_value.has_value();
83 bool nan = params_.allow_nan.value_or(!has_min && !has_max);
84 bool inf = params_.allow_infinity.value_or(!has_min || !has_max);
85 if (nan && (has_min || has_max)) {
86 throw std::invalid_argument(
87 "Cannot have allow_nan=true with min_value or max_value");
88 }
89 if (has_min && has_max && *params_.min_value > *params_.max_value) {
90 throw std::invalid_argument(
91 "Cannot have max_value < min_value");
92 }
93 if (inf && has_min && has_max) {
94 throw std::invalid_argument(
95 "Cannot have allow_infinity=true with both min_value and "
96 "max_value");
97 }
98 }
99
100 std::optional<BasicGenerator<T>> as_basic() const override {
101 constexpr int width = sizeof(T) * 8;
102 bool has_min = params_.min_value.has_value();
103 bool has_max = params_.max_value.has_value();
104 bool nan = params_.allow_nan.value_or(!has_min && !has_max);
105 bool inf = params_.allow_infinity.value_or(!has_min || !has_max);
106
107 hegel::internal::json::json schema = {
108 {"type", "float"},
109 {"exclude_min", params_.exclude_min},
110 {"exclude_max", params_.exclude_max},
111 {"allow_nan", nan},
112 {"allow_infinity", inf},
113 {"width", width}};
114 if (params_.min_value)
115 schema["min_value"] = *params_.min_value;
116 if (params_.max_value)
117 schema["max_value"] = *params_.max_value;
118 return BasicGenerator<T>{std::move(schema), &default_parse_raw<T>};
119 }
120
121 private:
122 FloatsParams<T> params_;
123 };
125
128
144 template <typename T = int64_t>
145 requires std::is_integral_v<T>
147 return Generator<T>(new IntegerGenerator<T>(std::move(params)));
148 }
149
166 template <typename T = double>
167 requires std::is_floating_point_v<T>
169 return Generator<T>(new FloatGenerator<T>(std::move(params)));
170 }
171
173
174} // namespace hegel::generators
The base class of all generators.
Definition core.h:157
Hegel generators.
Definition core.h:16
Generator< T > integers(IntegersParams< T > params={})
Generate random integers. For a given integral type T, produces values in the range [std::numeric_lim...
Definition numeric.h:146
Generator< T > floats(FloatsParams< T > params={})
Generate random floating point numbers.
Definition numeric.h:168
Parameters for floats() generator.
Definition numeric.h:28
bool exclude_min
If true, exclude min_value (exclusive bound).
Definition numeric.h:31
std::optional< T > min_value
Minimum value. Default: no minimum.
Definition numeric.h:29
std::optional< T > max_value
Maximum value. Default: no maximum.
Definition numeric.h:30
std::optional< bool > allow_nan
Allow NaN. Default: true if unbounded.
Definition numeric.h:36
bool exclude_max
If true, exclude max_value (exclusive bound).
Definition numeric.h:33
std::optional< bool > allow_infinity
Allow infinity. Default: true if unbounded.
Definition numeric.h:38
*‍/
Definition core.h:94
Parameters for integers() generator.
Definition numeric.h:17
std::optional< T > max_value
Maximum value (inclusive). Default: type maximum.
Definition numeric.h:21
std::optional< T > min_value
Minimum value (inclusive). Default: type minimum.
Definition numeric.h:19