@@ -184,13 +184,155 @@ template<typename value_type> struct partial_test {
184184 std::vector<value_type> m, s;
185185};
186186
187+ BNCH_SWT_HOST std::string generate_integer_part (uint64_t min_length = 1 , uint64_t max_length = 15 ) {
188+ uint64_t length = bnch_swt::random_generator<uint64_t >::impl (min_length, max_length);
189+
190+ if (length == 1 && bnch_swt::random_generator<uint64_t >::impl (0 , 1 ) == 0 && bnch_swt::random_generator<uint64_t >::impl (0 , 9 ) == 0 )
191+ return " 0" ;
192+
193+ std::string s;
194+ s += std::to_string (bnch_swt::random_generator<uint64_t >::impl (1 , 9 ));
195+
196+ for (uint64_t i = 1 ; i < length; ++i) {
197+ s += std::to_string (bnch_swt::random_generator<uint64_t >::impl (0 , 9 ));
198+ }
199+ return s;
200+ }
201+
202+ BNCH_SWT_HOST std::string maybe_add_sign (const std::string& s) {
203+ return (bnch_swt::random_generator<uint64_t >::impl (0 , 1 ) == 1 ) ? (" -" + s) : s;
204+ }
205+
206+ BNCH_SWT_HOST std::string generate_1_simple_integer () {
207+ return maybe_add_sign (generate_integer_part (1 , 10 ));
208+ }
209+
210+ BNCH_SWT_HOST std::string generate_2_simple_float () {
211+ std::string s = generate_integer_part (1 , 5 );
212+ s += " ." ;
213+
214+ uint64_t fractional_length = bnch_swt::random_generator<uint64_t >::impl (1 , 10 );
215+ for (uint64_t i = 0 ; i < fractional_length; ++i) {
216+ s += std::to_string (bnch_swt::random_generator<uint64_t >::impl (0 , 9 ));
217+ }
218+ return maybe_add_sign (s);
219+ }
220+
221+ BNCH_SWT_HOST std::string generate_3_scientific () {
222+ std::string s;
223+
224+ if (bnch_swt::random_generator<uint64_t >::impl (0 , 1 ) == 0 ) {
225+ s = generate_integer_part (1 , 3 ) + " ." ;
226+ s += std::to_string (bnch_swt::random_generator<uint64_t >::impl (0 , 9 ));
227+ } else {
228+ s = generate_integer_part (1 , 5 );
229+ }
230+
231+ s += (bnch_swt::random_generator<uint64_t >::impl (0 , 1 ) == 0 ? ' e' : ' E' );
232+ s += (bnch_swt::random_generator<uint64_t >::impl (0 , 1 ) == 0 ? ' +' : ' -' );
233+ uint64_t exponent = bnch_swt::random_generator<uint64_t >::impl (1 , 100 );
234+ s += std::to_string (exponent);
235+
236+ return maybe_add_sign (s);
237+ }
238+
239+ BNCH_SWT_HOST std::string generate_4_min_max_boundary () {
240+ if (bnch_swt::random_generator<uint64_t >::impl (0 , 1 ) == 0 ) {
241+ double mantissa = bnch_swt::random_generator<double >::impl (1.0 , 9.9 );
242+ uint64_t exponent = bnch_swt::random_generator<uint64_t >::impl (300 , 308 );
243+ double val = mantissa * std::pow (10.0 , exponent);
244+ if (bnch_swt::random_generator<uint64_t >::impl (0 , 1 ) == 1 )
245+ val = -val;
246+
247+ std::stringstream ss;
248+ ss << std::scientific << std::setprecision (16 ) << val;
249+ return ss.str ();
250+ } else {
251+ double mantissa = bnch_swt::random_generator<double >::impl (1.0 , 9.9 );
252+ uint64_t exponent = bnch_swt::random_generator<uint64_t >::impl (300 , 308 );
253+ double val = mantissa * std::pow (10.0 , static_cast <double >(-static_cast <int64_t >(exponent)));
254+ if (bnch_swt::random_generator<uint64_t >::impl (0 , 1 ) == 1 )
255+ val = -val;
256+
257+ std::stringstream ss;
258+ ss << std::scientific << std::setprecision (16 ) << val;
259+ return ss.str ();
260+ }
261+ }
262+
263+ BNCH_SWT_HOST std::string generate_5_precision_boundary () {
264+ std::string s;
265+ s += maybe_add_sign (std::to_string (bnch_swt::random_generator<uint64_t >::impl (1 , 9 )));
266+ s += " ." ;
267+
268+ for (uint64_t i = 0 ; i < 18 ; ++i) {
269+ s += std::to_string (bnch_swt::random_generator<uint64_t >::impl (0 , 9 ));
270+ }
271+
272+ if (bnch_swt::random_generator<uint64_t >::impl (0 , 1 ) == 0 ) {
273+ s += ' e' ;
274+ s += std::to_string (bnch_swt::random_generator<uint64_t >::impl (1 , 100 ));
275+ }
276+ return s;
277+ }
278+
279+ BNCH_SWT_HOST std::string generate_6_zero_subnormal () {
280+ if (bnch_swt::random_generator<uint64_t >::impl (0 , 1 ) == 0 ) {
281+ static constexpr std::array zero_forms = { " 0" , " 0.0" , " -0.0" , " 0e0" , " -0e5" , " 0.0e-10" };
282+ uint64_t index = bnch_swt::random_generator<uint64_t >::impl (0 , zero_forms.size () - 1 );
283+ return zero_forms[index];
284+ } else {
285+ double mantissa = bnch_swt::random_generator<double >::impl (1.0 , 9.9 );
286+ double val = mantissa * std::pow (10.0 , -315 );
287+
288+ std::stringstream ss;
289+ ss << std::scientific << std::setprecision (16 ) << val;
290+ return maybe_add_sign (ss.str ());
291+ }
292+ }
293+
294+ BNCH_SWT_HOST std::string generate_7_structural_edge () {
295+ static constexpr std::array edge_forms = { " 1e10" , " -9e-10" , " 0.1" , " -9.0" , " 1.2e0" , " -3e+0" , " 123.000000" , " 0.0000001" };
296+ uint64_t index = bnch_swt::random_generator<uint64_t >::impl (0 , edge_forms.size () - 1 );
297+ return edge_forms[index];
298+ }
299+
300+ BNCH_SWT_HOST std::string generate_random_double_string () {
301+ static constexpr std::array weights = { 40.0 , 30.0 , 10.0 , 5.0 , 5.0 , 5.0 , 5.0 };
302+
303+ static constexpr std::array generators = { generate_1_simple_integer, generate_2_simple_float, generate_3_scientific, generate_4_min_max_boundary,
304+ generate_5_precision_boundary, generate_6_zero_subnormal, generate_7_structural_edge };
305+
306+ uint64_t roll = bnch_swt::random_generator<uint64_t >::impl (0 , 99 );
307+
308+ uint64_t cumulative_weight = 0 ;
309+ for (size_t i = 0 ; i < weights.size (); ++i) {
310+ cumulative_weight += static_cast <uint64_t >(weights[i]);
311+ if (roll < cumulative_weight) {
312+ return generators[i]();
313+ }
314+ }
315+ return generators.back ()();
316+ }
317+
318+ BNCH_SWT_HOST double generate_random_double () {
319+ double test_double;
320+ do {
321+ std::string test_string = generate_random_double_string ();
322+ auto new_ptr = test_string.data () + test_string.size ();
323+ test_double= strtod (test_string.data (), &new_ptr);
324+ } while (test_double == std::numeric_limits<double >::infinity () || test_double == std::numeric_limits<double >::quiet_NaN () ||
325+ test_double == -std::numeric_limits<double >::infinity ());
326+ return test_double;
327+ }
328+
187329struct test_generator {
188330 template <jsonifier::concepts::string_t value_type> static value_type generate_value () {
189331 return bnch_swt::random_generator<std::string>::impl (bnch_swt::random_generator<uint64_t >::impl (16ull , 64ull ));
190332 }
191333
192334 template <jsonifier::concepts::float_t value_type> static value_type generate_value () {
193- return bnch_swt::random_generator< double >:: impl ();
335+ return generate_random_double ();
194336 }
195337
196338 template <jsonifier::concepts::bool_t value_type> static value_type generate_value () {
0 commit comments