tgen 1.5.0
Loading...
Searching...
No Matches
tgen.h
1/*
2 * Copyright (c) 2026 Bruno Monteiro
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#pragma once
24
25#include <algorithm>
26#include <bitset>
27#include <cerrno>
28#include <cmath>
29#include <cstdint>
30#include <cstdlib>
31#include <functional>
32#include <initializer_list>
33#include <iomanip>
34#include <iostream>
35#include <limits>
36#include <map>
37#include <optional>
38#include <queue>
39#include <random>
40#include <set>
41#include <sstream>
42#include <stdexcept>
43#include <string>
44#include <sys/types.h>
45#include <type_traits>
46#include <unordered_map>
47#include <unordered_set>
48#include <utility>
49#include <vector>
50
51namespace tgen {
52
53/**************************
54 * *
55 * GENERAL OPERATIONS *
56 * *
57 **************************/
58
59namespace detail {
60
61// Type aliases.
62using u128 = unsigned __int128;
63using i128 = __int128;
64
65/*
66 * Error handling.
67 */
68
69inline void throw_assertion_error(const std::string &condition,
70 const std::string &msg, const char *file,
71 int line) {
72 throw std::runtime_error("tgen: " + msg + " (assertion `" + condition +
73 "` failed at " + file + ":" +
74 std::to_string(line) + ")");
75}
76inline void throw_assertion_error(const std::string &condition,
77 const char *file, int line) {
78 throw std::runtime_error("tgen: assertion `" + condition + "` failed at " +
79 std::string(file) + ":" + std::to_string(line));
80}
81inline std::runtime_error error(const std::string &msg) {
82 return std::runtime_error("tgen: " + msg);
83}
84inline std::runtime_error contradiction_error(const std::string &type,
85 const std::string &msg = "") {
86 // Tried to generate a contradictory type.
87 std::string error_msg =
88 type + ": invalid " + type + " (contradictory restrictions)";
89 if (!msg.empty())
90 error_msg += ": " + msg;
91 return error(error_msg);
92}
93inline std::runtime_error
94complex_restrictions_error(const std::string &type,
95 const std::string &msg = "") {
96 // Tried to generate a type with too many distinct restrictions.
97 std::string error_msg =
98 type + ": cannot represent " + type + " (complex restrictions)";
99 if (!msg.empty())
100 error_msg += ": " + msg;
101 return error(error_msg);
102}
103inline void tgen_ensure_against_bug(bool cond, const std::string &msg = "") {
104 if (!cond) {
105 std::string error_msg;
106 if (!msg.empty())
107 error_msg = "tgen: " + msg + "\n";
108 error_msg += "tgen: THERE IS A BUG IN TGEN; PLEASE CONTACT MAINTAINERS";
109 throw std::runtime_error(error_msg);
110 }
111}
112
113// Ensures condition is true, with a clear error message on failure.
114#define tgen_ensure(cond, ...)
115 if (!(cond))
116 tgen::detail::throw_assertion_error(#cond, ##__VA_ARGS__, __FILE__,
117 __LINE__)
118
119// Registering checks.
120inline bool registered = false;
121inline void ensure_registered() {
122 tgen_ensure(registered,
123 "tgen was not registered! You should call "
124 "tgen::register_gen(argc, argv) before running tgen functions");
125}
126
127// Template magic to detect types at compile time.
128
129// Detects containers != std::string.
130template <typename T, typename = void> struct is_container : std::false_type {};
131template <typename T>
132struct is_container<T,
133 std::void_t<typename std::remove_reference_t<T>::value_type,
134 decltype(std::begin(std::declval<T>())),
135 decltype(std::end(std::declval<T>()))>>
136 : std::true_type {};
137// Exclude all basic_string variants
138template <typename Char, typename Traits, typename Alloc>
139struct is_container<std::basic_string<Char, Traits, Alloc>> : std::false_type {
140};
141template <typename Char, typename Traits, typename Alloc>
142struct is_container<const std::basic_string<Char, Traits, Alloc>>
143 : std::false_type {};
144template <typename Char, typename Traits, typename Alloc>
145struct is_container<std::basic_string<Char, Traits, Alloc> &>
146 : std::false_type {};
147template <typename Char, typename Traits, typename Alloc>
148struct is_container<const std::basic_string<Char, Traits, Alloc> &>
149 : std::false_type {};
150
151// Detects std::pair.
152template <typename T> struct is_pair : std::false_type {};
153template <typename A, typename B>
154struct is_pair<std::pair<A, B>> : std::true_type {};
155// Detects std::tuple.
156template <typename T> struct is_tuple : std::false_type {};
157template <typename... Ts>
158struct is_tuple<std::tuple<Ts...>> : std::true_type {};
159// Detects scalar (printed atomically).
160template <typename T>
161struct is_scalar
162 : std::bool_constant<!is_container<T>::value and !is_tuple<T>::value and
163 !is_pair<T>::value> {};
164// Detects complex container.
165template <typename T>
166struct is_container_multiline
167 : std::bool_constant<is_container<T>::value and
168 !is_scalar<typename std::remove_cv_t<
169 std::remove_reference_t<T>>::value_type>::value> {
170};
171// Detects complex std::pair.
172template <typename T> struct is_pair_multiline : std::false_type {};
173template <typename A, typename B>
174struct is_pair_multiline<std::pair<A, B>>
175 : std::bool_constant<!is_scalar<A>::value or !is_scalar<B>::value> {};
176// Detects complex std::tuple.
177template <typename Tuple> struct is_tuple_multiline : std::false_type {};
178template <typename... Ts>
179struct is_tuple_multiline<std::tuple<Ts...>>
180 : std::bool_constant<(!is_scalar<Ts>::value or ...)> {};
181
182// Used to return false at compile time only if evaluated.
183template <typename> inline constexpr bool dependent_false_v = false;
184
185/*
186 * Properties of custom types.
187 */
188
189// If type is sequential (list-like).
190using is_sequential_tag = void;
191
192// Detects associative containers.
193template <typename T, typename = void>
194struct is_associative_container : std::false_type {};
195template <typename T>
196struct is_associative_container<
197 T, std::void_t<typename T::key_type, typename T::key_compare>>
198 : std::true_type {};
199
200// Detects sequential generator values.
201template <typename T, typename = void>
202struct is_sequential : std::false_type {};
203template <typename T>
204struct is_sequential<
205 T, std::void_t<typename std::decay_t<T>::tgen_is_sequential_tag>>
206 : std::true_type {};
207
208/*
209 * Unique rng to use.
210 */
211
212// The single rng to be used by the library.
213inline std::mt19937 rng;
214
215/*
216 * Printing.
217 */
218
219// Print view struct for printing either a container or a sequential generator
220// element.
221template <typename T,
222 bool IsCont = detail::is_container<std::decay_t<T>>::value>
223struct print_cols_view;
224
225// Container.
226template <typename T> struct print_cols_view<T, true> {
227 const T &value;
228 decltype(std::begin(std::declval<const T &>())) it;
229
230 print_cols_view(const T &v) : value(v), it(v.begin()) {}
231
232 std::size_t size() const { return value.size(); }
233 decltype(auto) get(std::size_t) const { return *it; }
234 void advance() { ++it; }
235};
236
237// Sequential generator element.
238template <typename T> struct print_cols_view<T, false> {
239 const T &value;
240
241 print_cols_view(const T &v) : value(v) {}
242
243 std::size_t size() const { return value.size(); }
244 decltype(auto) get(std::size_t i) const {
245 return value[static_cast<int>(i)];
246 }
247 void advance() {}
248};
249
250/*
251 * Distinct generation.
252 */
253
254// Rejection cap is multiplier * |seen|; with one value left, falsely reporting
255// exhaustion has probability about e^{-84} < 10^{-36}.
256constexpr int distinct_attempt_multiplier = 84;
257
258// One rejection-sampling step for distinct generation.
259// O(T * log k + log^2 k) amortized expected time per call when generating k
260// distinct values and next() runs in O(T).
261template <typename Seen, typename Fn>
262auto try_generate_distinct(Seen &seen, Fn &&next, bool insert = true)
263 -> std::optional<std::invoke_result_t<Fn &>> {
264 using T = std::invoke_result_t<Fn &>;
265 size_t attempts =
266 distinct_attempt_multiplier * std::max<size_t>(1, seen.size());
267 for (size_t i = 0; i < attempts; ++i) {
268 T val = next();
269 if (insert) {
270 if (seen.insert(val).second)
271 return val;
272 } else if (seen.count(val) == 0)
273 return val;
274 }
275 return std::nullopt;
276}
277
278} // namespace detail
279
280/*
281 * Compiler configuration (see set_compiler).
282 */
283
284// Kinds of compilers.
285enum class compiler_kind { gcc, clang, unknown };
286
287// Compiler identity and version.
289 compiler_kind kind_;
290 int major_;
291 int minor_;
292
293 compiler_value(compiler_kind kind = compiler_kind::unknown, int major = 0,
294 int minor = 0)
295 : kind_(kind), major_(major), minor_(minor) {}
296};
297
298namespace detail {
299
300// Global C++ version value (0 means unknown).
301struct cpp_value {
302 int version_;
303
304 cpp_value(std::optional<int> version = std::nullopt)
305 : version_(version ? *version : 0) {
306 if (version) {
307 tgen_ensure(*version == 17 or *version == 20 or *version == 23,
308 "unsupported C++ version (use 17, 20, 23)");
309 }
310 }
311};
312
313inline cpp_value cpp;
314inline compiler_value compiler;
315
316} // namespace detail
317
318/*
319 * Base classes.
320 */
321
322// Needed for return type of some functions.
323template <typename T> struct list;
324
325// Generates distinct values of a function.
326template <typename Func, typename... Args> struct distinct {
327 Func func_;
328 std::tuple<Args...> args_;
329 using T = std::invoke_result_t<Func &, Args &...>;
330 std::set<T> seen_;
331
332 distinct(Func func, Args... args)
333 : func_(std::move(func)), args_(std::move(args)...) {}
334
335 // Generates a distinct value (i.e., one not returned before).
336 //
337 // Assume gen() produces a uniformly random value in O(T) time.
338 // Since duplicates are rejected, the expected number of trials over
339 // k successful generations is:
340 //
341 // sum_{i=1}^k k / i = O(k log k)
342 //
343 // (coupon collector argument).
344 //
345 // Each trial additionally performs O(log k) work to check/store
346 // previously generated values, yielding a total time of
347 // O((T + log k) * k log k).
348 //
349 // Thus, the amortized expected time per call is
350 // O(T * log k + log^2 k).
351 //
352 // With extremely small probability (< 1e-18), the algorithm may
353 // incorrectly report that no more distinct values exist.
354 auto gen() {
355 auto val = generate_distinct(true);
356 if (val)
357 return *val;
358
359 throw detail::error("distinct: no more distinct values");
360 }
361 template <typename U> auto gen(std::initializer_list<U> il) {
362 return gen(std::vector<U>(il));
363 }
364
365 // Generates a list of distinct values.
366 auto gen_list(int size) {
367 std::vector<T> res;
368 for (int i = 0; i < size; ++i)
369 res.push_back(gen());
370
371 return typename list<T>::value(res);
372 }
373
374 // Checks if there are no more distinct values.
375 // With extremely small probability (< 1e-18), the algorithm may
376 // incorrectly report that there are no more distinct values.
377 bool empty() { return generate_distinct(false) == std::nullopt; }
378
379 // Generates all distinct values.
380 auto gen_all() {
381 std::vector<T> res;
382 while (true) {
383 auto val = generate_distinct(true);
384 if (val)
385 res.push_back(*val);
386 else
387 break;
388 }
389 return typename list<T>::value(res);
390 }
391
392 // Nice error for `out << distinct`.
393 friend std::ostream &operator<<(std::ostream &out, const distinct &) {
394 static_assert(
395 detail::dependent_false_v<distinct>,
396 "distinct: cannot print a distinct generator. Maybe you forgot to "
397 "call `gen()`?");
398 return out;
399 }
400
401 private:
402 // Generates distinct value and inserts it if `insert` is true.
403 // Returns the value if found, otherwise returns std::nullopt.
404 auto generate_distinct(bool insert) {
405 return detail::try_generate_distinct(
406 seen_, [&] { return std::apply(func_, args_); }, insert);
407 }
408};
409template <typename Func, typename... Args>
410distinct(Func, Args...) -> distinct<Func, Args...>;
411
412// Base struct for generators.
413template <typename Gen> struct gen_base {
414 const Gen &self() const { return *static_cast<const Gen *>(this); }
415
416 template <typename... Args> auto gen_list(int size, Args &&...args) const {
417 std::vector<typename Gen::value> res;
418
419 for (int i = 0; i < size; ++i)
420 res.push_back(static_cast<const Gen *>(this)->gen(
421 std::forward<Args>(args)...));
422
423 return typename list<typename Gen::value>::value(res);
424 }
425
426 // Calls the generator until predicate is true.
427 template <typename Pred, typename... Args>
428 auto gen_until(Pred predicate, int max_tries, Args &&...args) const {
429 for (int i = 0; i < max_tries; ++i) {
430 typename Gen::value val = static_cast<const Gen *>(this)->gen(
431 std::forward<Args>(args)...);
432
433 if (predicate(val))
434 return val;
435 }
436
437 throw detail::error("could not generate value matching predicate");
438 }
439 template <typename Pred, typename T, typename... Args>
440 auto gen_until(Pred predicate, int max_tries, std::initializer_list<T> il,
441 Args &&...args) const {
442 return gen_until(predicate, max_tries, std::vector<T>(il),
443 std::forward<Args>(args)...);
444 }
445
446 // Distinct for generator.
447 template <typename... Args> auto distinct(Args &&...args) const {
448 return tgen::distinct(
449 [self = self()](auto &&...inner_args) mutable -> decltype(auto) {
450 return self.gen(
451 std::forward<decltype(inner_args)>(inner_args)...);
452 },
453 std::forward<Args>(args)...);
454 }
455 template <typename T, typename... Args>
456 auto distinct(std::initializer_list<T> il, Args &&...args) const {
457 return distinct(std::vector<T>(il), std::forward<Args>(args)...);
458 }
459
460 // Nice error for `out << generator`.
461 friend std::ostream &operator<<(std::ostream &out, const gen_base &) {
462 static_assert(detail::dependent_false_v<gen_base>,
463 "gen_base: cannot print a generator. Maybe you forgot to "
464 "call `gen()`?");
465 return out;
466 }
467};
468
469// Base class for generator values.
470template <typename Val> struct gen_value_base {
471 const Val &self() const { return *static_cast<const Val *>(this); }
472
473 bool operator<(const Val &rhs) const {
474 return self().to_std() < rhs.to_std();
475 }
476};
477
478namespace detail {
479
480// Detects generator values.
481template <typename T>
482struct is_generator_value
483 : std::is_base_of<gen_value_base<std::decay_t<T>>, std::decay_t<T>> {};
484
485} // namespace detail
486
487/*
488 * Easier printing.
489 */
490
491// Struct to print standard types to std::ostream;
492struct print {
493 std::string s_;
494
495 template <typename T> print(const T &val, char sep = ' ') {
496 std::ostringstream oss;
497 write(oss, val, sep);
498 s_ = oss.str();
499 }
500 template <typename T>
501 print(const std::initializer_list<T> &il, char sep = ' ') {
502 std::ostringstream oss;
503 write(oss, std::vector<T>(il), sep);
504 s_ = oss.str();
505 }
506 template <typename T>
507 print(const std::initializer_list<std::initializer_list<T>> &il,
508 char sep = ' ') {
509 std::ostringstream oss;
510 std::vector<std::vector<T>> mat;
511 for (const auto &i : il)
512 mat.push_back(i);
513 write(oss, mat, sep);
514 s_ = oss.str();
515 }
516
517 template <typename T> void write(std::ostream &os, const T &val, char sep) {
518 if constexpr (detail::is_pair<T>::value) {
519 if constexpr (detail::is_pair_multiline<T>::value) {
520 write(os, val.first, sep);
521 os << '\n';
522 write(os, val.second, sep);
523 } else {
524 // Use space for inner separator.
525 write(os, val.first, ' ');
526 os << sep;
527 write(os, val.second, ' ');
528 }
529 } else if constexpr (detail::is_tuple<T>::value)
530 write_tuple(os, val, sep);
531 else if constexpr (detail::is_container<T>::value)
532 write_container(os, val, sep);
533 else if constexpr (std::is_same_v<T, detail::i128> or
534 std::is_same_v<T, detail::u128>)
535 write_128_number(os, val);
536 else
537 os << val;
538 }
539
540 // Writes 128 bit number.
541 template <typename T> void write_128_number(std::ostream &os, T num) {
542 static const long long BASE = 1e18;
543
544 if (num < 0) {
545 os << '-';
546 // Unsigned magnitude also represents the signed minimum.
547 write_128_number(os,
548 detail::u128(0) - static_cast<detail::u128>(num));
549 return;
550 }
551
552 if (num >= BASE) {
553 write_128_number(os, num / BASE);
554 os << std::setw(18) << std::setfill('0')
555 << static_cast<long long>(num % BASE);
556 } else
557 os << static_cast<long long>(num);
558 }
559 // Writes container, checking separator.
560 template <typename C>
561 void write_container(std::ostream &os, const C &container, char sep) {
562 bool first = true;
563
564 for (const auto &e : container) {
565 if (!first)
566 os << (detail::is_container_multiline<C>::value ? '\n' : sep);
567 first = false;
568 write(os, e, detail::is_container_multiline<C>::value ? sep : ' ');
569 }
570 }
571
572 // Writes tuple, checking separator.
573 template <typename Tuple, size_t... I>
574 void write_tuple_impl(std::ostream &os, const Tuple &tp, char sep,
575 std::index_sequence<I...>) {
576 bool first = true;
577 ((os << (first ? (first = false, "")
578 : (detail::is_tuple_multiline<Tuple>::value
579 ? "\n"
580 : std::string(1, sep))),
581 write(os, std::get<I>(tp),
582 detail::is_tuple_multiline<Tuple>::value ? sep : ' ')),
583 ...);
584 }
585 template <typename T>
586 void write_tuple(std::ostream &os, const T &tp, char sep) {
587 write_tuple_impl(os, tp, sep,
588 std::make_index_sequence<std::tuple_size<T>::value>{});
589 }
590
591 friend std::ostream &operator<<(std::ostream &out, const print &pr) {
592 return out << pr.s_;
593 }
594};
595
596// Prints in a new line.
597struct println : print {
598 template <typename T>
599 println(const T &val, char sep = ' ') : print(val, sep) {}
600 template <typename T>
601 println(const std::initializer_list<T> &il, char sep = ' ')
602 : print(il, sep) {}
603 template <typename T>
604 println(const std::initializer_list<std::initializer_list<T>> &il,
605 char sep = ' ')
606 : print(il, sep) {}
607
608 friend std::ostream &operator<<(std::ostream &out, const println &pr) {
609 return out << pr.s_ << '\n';
610 }
611};
612
613// Prints container / sequential generator value on its own column.
614// Example:
615// A = {1, 2, 3}, B = {4, 2, 5}
616// print_each(A, B) will print:
617// "1 4
618// 2 2
619// 3 5
620//",
621// that is, it prints the end of the line for all lines.
622template <typename... Args> struct print_cols {
623 std::string s_;
624
625 print_cols(const Args &...args) {
626 static_assert(
627 ((detail::is_container<std::decay_t<Args>>::value or
628 detail::is_sequential<std::decay_t<Args>>::value) and
629 ...),
630 "print_cols: arguments must be containers or sequential generator "
631 "values");
632 std::ostringstream oss;
633 write(oss, args...);
634 s_ = oss.str();
635 }
636
637 void write(std::ostream &os, const Args &...args) {
638 auto views = std::apply(
639 [](const Args &...inner_args) {
640 return std::make_tuple(
641 detail::print_cols_view<decltype(inner_args)>{
642 inner_args}...);
643 },
644 std::forward_as_tuple(args...));
645
646 const std::size_t n = std::get<0>(views).size();
647
648 auto check = [&](const auto &v) {
649 tgen_ensure(v.size() == n, "print_cols: sizes should be the same");
650 };
651 std::apply([&](const auto &...v) { (check(v), ...); }, views);
652
653 for (std::size_t i = 0; i < n; ++i) {
654 bool first = true;
655
656 std::apply(
657 [&](const auto &...v) {
658 ((os << (first ? "" : " ") << print(v.get(i)),
659 first = false),
660 ...);
661 },
662 views);
663
664 os << '\n';
665
666 std::apply([](auto &...v) { (v.advance(), ...); }, views);
667 }
668 }
669
670 friend std::ostream &operator<<(std::ostream &out, const print_cols &pr) {
671 return out << pr.s_;
672 }
673};
674
675/*
676 * Global random operations.
677 */
678
679namespace detail {
680
681// libstdc++ accepts std::uniform_int_distribution with narrow integral types
682// (char/signed char/unsigned char/short/bool), but libc++ rejects them with a
683// hard static_assert ("IntType must be a supported integer type"). Promote such
684// types to a width the standard guarantees, preserving signedness, so the same
685// `next<T>` works across both standard libraries (e.g. Apple clang / libc++).
686template <typename T>
687using uniform_int_t = std::conditional_t<
688 (sizeof(T) >= sizeof(short)), T,
689 std::conditional_t<std::is_signed_v<T>, int, unsigned int>>;
690
691// Floating distributions require finite endpoints and a representable span.
692template <typename T> void ensure_floating_range(T left, T right) {
694 std::isfinite(left) and std::isfinite(right) and left <= right and
695 std::isfinite(right - left),
696 "floating range must have finite ordered endpoints and a finite width");
697}
698
699} // namespace detail
700
701// Returns a uniformly random number in [0, right)
702// O(1).
703template <typename T> T next(T right) {
704 detail::ensure_registered();
705 if constexpr (std::is_integral_v<T>) {
706 tgen_ensure(right >= 1, "value for `next` must be valid");
707 return static_cast<T>(
708 std::uniform_int_distribution<detail::uniform_int_t<T>>(
709 0,
710 static_cast<detail::uniform_int_t<T>>(right) - 1)(detail::rng));
711 } else if constexpr (std::is_floating_point_v<T>) {
712 detail::ensure_floating_range(T(0), right);
713 return std::uniform_real_distribution<T>(0, right)(detail::rng);
714 } else
715 throw detail::error("invalid type for next (" +
716 std::string(typeid(T).name()) + ")");
717}
718
719// Returns a uniformly random number in [left, right].
720// For floating-point types, uses uniform_real_distribution ([left, right) in
721// C++), equivalent to [left, right] because the right endpoint has probability
722// zero.
723// O(1).
724template <typename T> T next(T left, T right) {
725 detail::ensure_registered();
726 tgen_ensure(left <= right, "range for `next` must be valid");
727 if constexpr (std::is_integral_v<T>)
728 return static_cast<T>(
729 std::uniform_int_distribution<detail::uniform_int_t<T>>(
730 static_cast<detail::uniform_int_t<T>>(left),
731 static_cast<detail::uniform_int_t<T>>(right))(detail::rng));
732 else if constexpr (std::is_floating_point_v<T>) {
733 detail::ensure_floating_range(left, right);
734 return std::uniform_real_distribution<T>(left, right)(detail::rng);
735 } else
736 throw detail::error("invalid type for next (" +
737 std::string(typeid(T).name()) + ")");
738}
739
740namespace detail {
741
742// Maps a unit sample to an integral interval. half_open excludes right.
743template <typename T>
744T scale_skewed_integer(T left, T right, double x, bool half_open) {
745 // Ordinary integer ranges fit in 64 bits, including their full span.
746 if constexpr (sizeof(T) < sizeof(uint64_t)) {
747 long long lo = left, hi = right;
748 long long offset =
749 static_cast<long long>(x * static_cast<double>(hi - lo));
750 return static_cast<T>(std::min(lo + offset, hi - half_open));
751 } else {
752 // Widen before subtracting or reconstructing a value: the span of
753 // signed 64-bit endpoints can exceed LLONG_MAX. Rounded endpoints
754 // must also be clamped before narrowing to the output type.
755 i128 lo = left, hi = right, span = hi - lo;
756 // Keep ordinary ranges on the double/64-bit fast path. The margin
757 // below LLONG_MAX makes the conversion safe even after rounding.
758 if (span <= (i128(1) << 62)) {
759 long long offset =
760 static_cast<long long>(x * static_cast<double>(span));
761 offset = std::min(offset, static_cast<long long>(span) - half_open);
762 return static_cast<T>(lo + offset);
763 }
764 i128 offset = static_cast<i128>(static_cast<long double>(x) *
765 static_cast<long double>(span));
766 return static_cast<T>(std::min(lo + offset, hi - half_open));
767 }
768}
769
770} // namespace detail
771
772// Skewed next.
773//
774// Returns a random number in [0, right) with a bias controlled by `w`.
775// - w = 0:
776// Uniform distribution.
777// - w > 0:
778// Returns the maximum of (w + 1) independent uniform samples.
779// Biases the distribution toward larger values.
780// The resulting density is proportional to:
781// f(x) = x^w
782// In particular:
783// w = 1 -> linear bias
784// w = 2 -> quadratic bias
785// w = 3 -> cubic bias
786// - w < 0:
787// Returns the minimum of (-w + 1) independent uniform samples.
788// Symmetric to the w > 0 case.
789// The continuous version corresponds to Beta distributions:
790// w > 0 -> Beta(w + 1, 1)
791// w < 0 -> Beta(1, -w + 1)
792// For |w| > 5, the distribution is approximate.
793// O(1).
794template <typename T> T wnext(T right, int w) {
795 // For small |w|, use the naive approach.
796 // Avoid abs(INT_MIN), which overflows.
797 if (-5 <= w and w <= 5) {
798 T val = next<T>(right);
799 for (int i = 0; i < w; ++i)
800 val = std::max(val, next<T>(right));
801 for (int i = 0; i < -w; ++i)
802 val = std::min(val, next<T>(right));
803 return val;
804 }
805
806 if constexpr (std::is_floating_point_v<T>)
807 detail::ensure_floating_range(T(0), right);
808
809 // Convert w before adding or negating to avoid int overflow.
810 double x, r = next<double>(0, 1);
811
812 if (w >= 0) {
813 x = std::pow(r, 1.0 / (static_cast<double>(w) + 1.0));
814 } else {
815 x = 1.0 - std::pow(r, 1.0 / (-static_cast<double>(w) + 1.0));
816 }
817
818 if constexpr (std::is_integral_v<T>) {
819 tgen_ensure(right >= 1, "value for `wnext` must be valid");
820 return detail::scale_skewed_integer<T>(0, right, x, true);
821 } else
822 return T(x * right);
823}
824
825// Returns a random number in [left, right] with a bias controlled by `w`.
826// O(1).
827template <typename T> T wnext(T left, T right, int w) {
828 // For small |w|, use the naive approach.
829 // Avoid abs(INT_MIN), which overflows.
830 if (-5 <= w and w <= 5) {
831 T val = next<T>(left, right);
832 for (int i = 0; i < w; ++i)
833 val = std::max(val, next<T>(left, right));
834 for (int i = 0; i < -w; ++i)
835 val = std::min(val, next<T>(left, right));
836 return val;
837 }
838
839 if constexpr (std::is_floating_point_v<T>)
840 detail::ensure_floating_range(left, right);
841
842 // Convert w before adding or negating to avoid int overflow.
843 double x, r = next<double>(0, 1);
844
845 if (w >= 0) {
846 x = std::pow(r, 1.0 / (static_cast<double>(w) + 1.0));
847 } else {
848 x = 1.0 - std::pow(r, 1.0 / (-static_cast<double>(w) + 1.0));
849 }
850
851 if constexpr (std::is_integral_v<T>) {
852 tgen_ensure(left <= right, "range for `wnext` must be valid");
853 return detail::scale_skewed_integer(left, right, x, false);
854 } else
855 return left + T(x * (right - left));
856}
857
858namespace detail {
859
860// Uniformly random 128 bit number in [0, total).
861// O(1) expected.
862inline u128 next128(u128 total) {
863 tgen_ensure(total > 0, "next128: total must be positive");
864
865 // Largest multiple of total less than 2^128.
866 u128 limit = (u128(-1) / total) * total;
867
868 while (true) {
869 // Generate uniform 128-bit random number.
870 u128 r = (u128(next<uint64_t>(0, std::numeric_limits<uint64_t>::max()))
871 << 64) |
872 next<uint64_t>(0, std::numeric_limits<uint64_t>::max());
873
874 if (r < limit)
875 return r % total;
876 }
877}
878
879} // namespace detail
880
881// Weighted sampler.
882//
883// Generates indices with probability proportional to `distribution`, using
884// alias method.
885//
886// Internally, integral weights are accumulated in unsigned __int128 (exact);
887// floating-point weights are accumulated in double.
888// <O(n), O(1)>.
889template <typename T> struct weighted_sampler {
890 static_assert(std::is_arithmetic_v<T>,
891 "weighted_sampler requires an arithmetic weight type");
892
893 // Internal storage type: `u128` for integral inputs (exact arithmetic),
894 // `double` for floating-point inputs.
895 using storage_t =
897
898 int n_;
899 std::vector<storage_t> weight_;
900 std::vector<int> alias_;
901 storage_t total_;
902
903 // Creates an alias method for generating indices with probability
904 // proportional to the distribution.
905 // O(n).
906 weighted_sampler(const std::vector<T> &distribution)
907 : n_(static_cast<int>(distribution.size())), alias_(n_) {
908 tgen_ensure(distribution.size() > 0,
909 "weighted_sampler: distribution must be non-empty");
910 for (const auto &w : distribution) {
911 tgen_ensure(w >= 0,
912 "weighted_sampler: distribution must be non-negative");
913 if constexpr (std::is_floating_point_v<T>)
914 tgen_ensure(std::isfinite(w),
915 "weighted_sampler: weights must be finite");
916 }
917
918 total_ = std::accumulate(distribution.begin(), distribution.end(),
919 storage_t(0));
920
921 T scale = T(1);
922 bool rescale = false;
923 if constexpr (std::is_floating_point_v<T>) {
924 // Rescale to avoid overflow and coarse threshold rounding when
925 // the total underflows or is subnormal.
926 rescale = !std::isfinite(total_) or
927 total_ < std::numeric_limits<double>::min() or
928 total_ > std::numeric_limits<double>::max() / n_;
929 if (rescale) {
930 // A common scale preserves the probabilities.
931 scale =
932 *std::max_element(distribution.begin(), distribution.end());
933 tgen_ensure(scale > 0,
934 "weighted_sampler: total weight must be positive");
935 // Divide in T before narrowing tiny long double weights.
936 total_ = 0;
937 for (const auto &w : distribution)
938 total_ += static_cast<double>(w / scale);
939 }
940 }
941
942 tgen_ensure(total_ > 0,
943 "weighted_sampler: total weight must be positive");
944
945 std::queue<int> big, small;
946 for (int i = 0; i < n_; ++i) {
947 if constexpr (std::is_floating_point_v<T>)
948 weight_.push_back(storage_t(n_) *
949 storage_t(rescale ? distribution[i] / scale
950 : distribution[i]));
951 else
952 weight_.push_back(storage_t(n_) * storage_t(distribution[i]));
953 if (weight_[i] < total_)
954 small.push(i);
955 else
956 big.push(i);
957 }
958
959 while (!small.empty() and !big.empty()) {
960 int s = small.front();
961 small.pop();
962 int b = big.front();
963 big.pop();
964
965 alias_[s] = b;
966
967 weight_[b] -= total_ - weight_[s];
968 if (weight_[b] < total_)
969 small.push(b);
970 else
971 big.push(b);
972 }
973
974 if constexpr (std::is_integral_v<T>) {
975 detail::tgen_ensure_against_bug(
976 small.empty(), "weighted_sampler: small must be empty");
977 } else {
978 // Rounding can leave a nearly full column classified as small.
979 while (!small.empty()) {
980 int i = small.front();
981 small.pop();
982 weight_[i] = total_;
983 alias_[i] = i;
984 }
985 }
986
987 // The remaining elements should have weight equal to total and be
988 // assigned to themselves.
989 while (!big.empty()) {
990 int b = big.front();
991 big.pop();
992 if constexpr (std::is_integral_v<T>) {
993 detail::tgen_ensure_against_bug(
994 weight_[b] == total_,
995 "weighted_sampler: weight of big element must be total");
996 }
997 alias_[b] = b;
998 }
999 }
1000 weighted_sampler(const std::initializer_list<T> &distribution)
1001 : weighted_sampler(std::vector<T>(distribution)) {}
1002
1003 // Uniformly random value in [0, total). Overloaded so next() can dispatch
1004 // at compile time to the right primitive for the chosen `storage_t`.
1005 static detail::u128 sample_below(detail::u128 total) {
1006 return detail::next128(total);
1007 }
1008 static double sample_below(double total) {
1009 return tgen::next<double>(0, total);
1010 }
1011
1012 // Generates a random index with probability proportional to the
1013 // distribution.
1014 // O(1).
1015 size_t next() const {
1016 int i = tgen::next<int>(0, n_ - 1);
1017 return sample_below(total_) < weight_[i] ? i : alias_[i];
1018 }
1019};
1020template <typename T>
1021weighted_sampler(const std::vector<T> &) -> weighted_sampler<T>;
1022template <typename T>
1023weighted_sampler(const std::initializer_list<T> &) -> weighted_sampler<T>;
1024
1025// Returns i with probability proportional to distribution[i].
1026// O(|distribution|).
1027template <typename T>
1028size_t next_by_distribution(const std::vector<T> &distribution) {
1029 return weighted_sampler(distribution).next();
1030}
1031template <typename T>
1032size_t next_by_distribution(const std::initializer_list<T> &distribution) {
1033 return next_by_distribution(std::vector<T>(distribution));
1034}
1035
1036// Returns a vector of k indices with probability proportional to
1037// `distribution`. Uses alias method.
1038// O(k + |distribution|).
1039template <typename T>
1041 const std::vector<T> &distribution) {
1042 tgen_ensure(distribution.size() > 0, "distribution must be non-empty");
1043 tgen_ensure(k >= 0, "number of elements to choose must be non-negative");
1044
1045 weighted_sampler am(distribution);
1046 std::vector<int> res;
1047 for (int i = 0; i < k; ++i)
1048 res.push_back(static_cast<int>(am.next()));
1049 return res;
1050}
1051template <typename T>
1052std::vector<int>
1053many_by_distribution(int k, const std::initializer_list<T> &distribution) {
1054 return many_by_distribution(k, std::vector<T>(distribution));
1055}
1056
1057// Shuffles [first, last) inplace uniformly, for RandomAccessIterator.
1058// O(|container|).
1059template <typename It> void shuffle(It first, It last) {
1060 if (first == last)
1061 return;
1062
1063 for (It i = first + 1; i != last; ++i)
1064 std::iter_swap(i, first + next(0, static_cast<int>(i - first)));
1065}
1066
1067// Shuffles container uniformly.
1068// O(|container|).
1069template <typename C> [[nodiscard]] auto shuffled(const C &container) {
1070 if constexpr (detail::is_associative_container<C>::value) {
1071 std::vector<typename C::value_type> vec(container.begin(),
1072 container.end());
1073 shuffle(vec.begin(), vec.end());
1074 return vec;
1075 } else {
1076 auto new_container = container;
1077 shuffle(new_container.begin(), new_container.end());
1078 return new_container;
1079 }
1080}
1081template <typename T>
1082[[nodiscard]] std::vector<T> shuffled(const std::initializer_list<T> &il) {
1083 return shuffled(std::vector<T>(il));
1084}
1085
1086// Returns a random element from [first, last) uniformly.
1087// O(1) for random_access_iterator, O(|last - first|) otherwise.
1088template <typename It> typename It::value_type pick(It first, It last) {
1089 int size = static_cast<int>(std::distance(first, last));
1090 tgen_ensure(size > 0, "cannot pick from empty range");
1091 It it = first;
1092 std::advance(it, next(0, size - 1));
1093 return *it;
1094}
1095
1096// Returns a random element from container uniformly.
1097// O(1) for random_access_iterator, O(|container|) otherwise.
1098template <typename C> typename C::value_type pick(const C &container) {
1099 return pick(container.begin(), container.end());
1100}
1101template <typename T> T pick(const std::initializer_list<T> &il) {
1102 return pick(std::vector<T>(il));
1103}
1104
1105// Returns container[i] with probability proportional to distribution[i].
1106// O(1) for random_access_iterator, O(|container|) otherwise.
1107template <typename C, typename T>
1108typename C::value_type pick_by_distribution(const C &container,
1109 std::vector<T> distribution) {
1110 tgen_ensure(container.size() == distribution.size(),
1111 "container and distribution must have the same size");
1112 auto it = container.begin();
1113 std::advance(it, next_by_distribution(distribution));
1114 return *it;
1115}
1116template <typename C, typename T>
1117typename C::value_type
1118pick_by_distribution(const C &container,
1119 const std::initializer_list<T> &distribution) {
1120 return pick_by_distribution(container, std::vector<T>(distribution));
1121}
1122template <typename T, typename U>
1123T pick_by_distribution(const std::initializer_list<T> &il,
1124 const std::vector<U> &distribution) {
1125 return pick_by_distribution(std::vector<T>(il), distribution);
1126}
1127template <typename T, typename U>
1128T pick_by_distribution(const std::initializer_list<T> &il,
1129 const std::initializer_list<U> &distribution) {
1130 return pick_by_distribution(std::vector<T>(il),
1131 std::vector<U>(distribution));
1132}
1133
1134// Chooses k values uniformly from container, as in a subsequence of size k.
1135// Returns a copy. O(|container|).
1136template <typename C> C choose(const C &container, int k) {
1137 tgen_ensure(0 < k and k <= static_cast<int>(container.size()),
1138 "number of elements to choose must be valid");
1139 std::vector<typename C::value_type> new_vec;
1140 C new_container;
1141 int need = k, left = static_cast<int>(container.size());
1142 for (auto cur_it = container.begin(); cur_it != container.end(); ++cur_it) {
1143 if (next(1, left--) <= need) {
1144 new_container.insert(new_container.end(), *cur_it);
1145 need--;
1146 }
1147 }
1148 return new_container;
1149}
1150template <typename T>
1151std::vector<T> choose(const std::initializer_list<T> &il, int k) {
1152 return choose(std::vector<T>(il), k);
1153}
1154
1155// Number distinct generator for integral types.
1156// Optimized for performance (unordered_map virtual list; gen_list uses array
1157// pool, complement, or sparse sampling).
1158template <typename T> struct distinct_range {
1160 // The full 64-bit domain has 2^64 elements; smaller domains need only
1161 // a 64-bit count. Indices themselves still fit in index_type.
1162 using count_type = std::conditional_t<(sizeof(T) < sizeof(uint64_t)),
1163 uint64_t, detail::u128>;
1164 T left_, right_;
1165 count_type num_available_;
1166 // In sparse mode, positions [0, num_available_) map to offsets from left_.
1167 std::unordered_map<index_type, index_type> virtual_list_;
1168 std::vector<T> pool_;
1169 bool uses_pool_ = false;
1170
1171 // When the range fits in memory, sample via array Fisher–Yates.
1172 static constexpr size_t array_pool_max = size_t{1} << 23;
1173
1174 // Generator of distinct values in [left, right].
1175 distinct_range(T left, T right)
1176 : left_(left), right_(right), num_available_(range_span()) {}
1177
1178 // Returns the number of distinct values left to generate.
1179 count_type size() const { return num_available_; }
1180
1181 // Generates a random value in [left_, right_] that has not been generated
1182 // yet.
1183 // O(log n).
1184 T gen() {
1185 // One iteration of Fisher–Yates.
1186 tgen_ensure(size() > 0, "distinct_range: no more values to generate");
1187
1188 if (uses_pool_) {
1189 size_t i = next<size_t>(pool_.size());
1190 T result = pool_[i];
1191 pool_[i] = pool_.back();
1192 pool_.pop_back();
1193 --num_available_;
1194 return result;
1195 }
1196
1197 index_type j = static_cast<index_type>(size() - 1);
1198 index_type i = next<index_type>(0, j);
1199
1200 auto vi_it = virtual_list_.find(i);
1201 index_type vi = vi_it == virtual_list_.end() ? i : vi_it->second;
1202 auto vj_it = virtual_list_.find(j);
1203 index_type vj = vj_it == virtual_list_.end() ? j : vj_it->second;
1204 virtual_list_[i] = vj;
1205
1206 --num_available_;
1207
1208 return value_at(vi);
1209 }
1210
1211 // Generates a list of distinct values.
1212 // Optimized for performance (array pool, complement, or sparse sampling).
1213 // Expected O(count), plus O(r) to materialize a pool of r remaining values.
1214 auto gen_list(int count) {
1215 tgen_ensure(count >= 0, "distinct_range: size must be nonnegative");
1216 tgen_ensure(static_cast<count_type>(count) <= num_available_,
1217 "distinct_range: no more values to generate");
1218
1219 if (count == 0)
1220 return typename list<T>::value(std::vector<T>{});
1221
1222 std::vector<T> res;
1223 const size_t sample_count = static_cast<size_t>(count);
1224 if (!uses_pool_ and num_available_ <= array_pool_max) {
1225 // Materialize the remaining permutation, respecting earlier draws.
1226 pool_.resize(static_cast<size_t>(num_available_));
1227 if (virtual_list_.empty()) {
1228 // Widen offsets instead of incrementing T past its maximum.
1229 const detail::i128 first = left_;
1230 for (size_t i = 0; i < pool_.size(); ++i)
1231 pool_[i] = static_cast<T>(first + i);
1232 } else {
1233 for (size_t i = 0; i < pool_.size(); ++i)
1234 pool_[i] =
1235 value_at(mapped_index(static_cast<index_type>(i)));
1236 }
1237 virtual_list_.clear();
1238 uses_pool_ = true;
1239 }
1240 if (uses_pool_) {
1241 // Local storage keeps the batch loop fast; the moves do not copy.
1242 auto pool = std::move(pool_);
1243 const size_t remaining = pool.size();
1244 // Put sampled values at the end; retain the prefix for later draws.
1245 for (size_t i = 0; i < sample_count; ++i) {
1246 size_t last = remaining - i - 1;
1247 size_t j = next<size_t>(0, last);
1248 std::swap(pool[j], pool[last]);
1249 }
1250 res.assign(pool.end() - count, pool.end());
1251 pool.resize(remaining - sample_count);
1252 num_available_ -= sample_count;
1253 pool_ = std::move(pool);
1254 } else if (count_type(sample_count) * 2 > num_available_) {
1255 res = sample_complement(sample_count);
1256 } else {
1257 virtual_list_.reserve(virtual_list_.size() + sample_count * 2);
1258 res.reserve(sample_count);
1259 for (size_t i = 0; i < sample_count; ++i)
1260 res.push_back(gen());
1261 }
1262 return typename list<T>::value(std::move(res));
1263 }
1264
1265 // Generates all distinct values.
1266 // O(n) when the range fits in memory; O(n log n) otherwise.
1267 auto gen_all() {
1268 // gen_list takes int; reject an unrepresentable count before narrowing.
1269 tgen_ensure(size() <= std::numeric_limits<int>::max(),
1270 "distinct_range: too many values for gen_all");
1271 return gen_list(static_cast<int>(size()));
1272 }
1273
1274 private:
1275 index_type mapped_index(index_type i) const {
1276 auto it = virtual_list_.find(i);
1277 return it == virtual_list_.end() ? i : it->second;
1278 }
1279
1280 // Sample the smaller excluded set of remaining positions, then retain it
1281 // as the next virtual list. Called only when the remaining count fits
1282 // size_t.
1283 std::vector<T> sample_complement(size_t count) {
1284 const size_t remaining = static_cast<size_t>(num_available_);
1285 const size_t excluded_count = remaining - count;
1286 std::unordered_set<index_type> excluded;
1287 excluded.reserve(excluded_count);
1288 // Floyd's sampling: on a collision, j is a new excluded position.
1289 for (size_t j = count; j < remaining; ++j) {
1290 index_type i = next<index_type>(0, static_cast<index_type>(j));
1291 if (!excluded.insert(i).second)
1292 excluded.insert(static_cast<index_type>(j));
1293 }
1294
1295 std::unordered_map<index_type, index_type> next_virtual;
1296 next_virtual.reserve(excluded_count);
1297 std::vector<T> res;
1298 res.reserve(count);
1299 index_type slot = 0;
1300 for (size_t i = 0; i < remaining; ++i) {
1301 index_type index = static_cast<index_type>(i);
1302 index_type mapped = mapped_index(index);
1303 if (excluded.count(index))
1304 next_virtual[slot++] = mapped;
1305 else
1306 res.push_back(value_at(mapped));
1307 }
1308 virtual_list_ = std::move(next_virtual);
1309 num_available_ = excluded_count;
1310 // A uniform subset also needs a uniform order for gen_list/gen_all.
1311 tgen::shuffle(res.begin(), res.end());
1312 return res;
1313 }
1314
1315 // Returns right_ - left_ + 1.
1316 // O(1).
1317 count_type range_span() const {
1318 if (left_ > right_)
1319 return 0;
1320 // Widen before subtraction; even unsigned 64-bit counts can overflow.
1321 return static_cast<count_type>(detail::i128(right_) - left_ + 1);
1322 }
1323
1324 T value_at(index_type index) const {
1325 // An offset may exceed signed T even though the final value fits.
1326 return static_cast<T>(detail::i128(left_) + index);
1327 }
1328};
1329
1330// Distinct generator for containers.
1331template <typename T> struct distinct_container {
1332 std::vector<T> list_;
1333 distinct_range<size_t> idx_;
1334
1335 // Creates a distinct container generator for the given container.
1336 template <typename C>
1337 distinct_container(const C &container)
1339 // Represent an empty container explicitly, not as [0, SIZE_MAX].
1340 idx_(list_.empty() ? 1 : 0, list_.empty() ? 0 : list_.size() - 1) {}
1341 distinct_container(const std::initializer_list<T> &il)
1342 : distinct_container(std::vector<T>(il)) {}
1343
1344 // Returns the number of distinct elements left to generate.
1345 size_t size() const { return static_cast<size_t>(idx_.size()); }
1346
1347 // Generates a random element from container uniformly.
1348 // O(log n).
1349 T gen() { return list_[idx_.gen()]; }
1350
1351 // Generates a list of distinct values.
1352 // O(size * log(n)).
1353 auto gen_list(int size) {
1354 std::vector<T> res;
1355 for (int i = 0; i < size; ++i)
1356 res.push_back(gen());
1357 return typename list<T>::value(res);
1358 }
1359
1360 // Generates all distinct values.
1361 // O(n log(n))
1362 auto gen_all() {
1363 std::vector<T> res;
1364 while (size() > 0)
1365 res.push_back(gen());
1366 return typename list<T>::value(res);
1367 }
1368};
1369template <typename C>
1370distinct_container(const C &) -> distinct_container<typename C::value_type>;
1371
1372/************
1373 * *
1374 * OPTS *
1375 * *
1376 ************/
1377
1378/*
1379 * Opts - options given to the generator.
1380 *
1381 * Incompatible with testlib.
1382 *
1383 * Opts are a list of either positional or named options.
1384 *
1385 * Named options are given in one of the following formats:
1386 * 1) -keyname=value or --keyname=value (ex. -n=10 , --test-count=20)
1387 * 2) -keyname value or --keyname value (ex. -n 10 , --test-count 20)
1388 *
1389 * Positional options are numbered from 0 sequentially.
1390 * For example, for "10 -n=20 str" positional option 1 is the string "str".
1391 */
1392
1393/*
1394 * C++ version selection.
1395 */
1396
1397// Sets C++ version.
1398inline void set_cpp_version(int version) {
1399 detail::cpp = detail::cpp_value(version);
1400}
1401
1402/*
1403 * Compiler selection.
1404 */
1405
1406// GCC compiler type.
1407inline compiler_value gcc(int major = 0, int minor = 0) {
1408 return {compiler_kind::gcc, major, minor};
1409}
1410
1411// Clang compiler type.
1412inline compiler_value clang(int major = 0, int minor = 0) {
1413 return {compiler_kind::clang, major, minor};
1414}
1415
1416// Sets compiler.
1417inline void set_compiler(compiler_value compiler) {
1418 detail::compiler.kind_ = compiler.kind_;
1419 detail::compiler.major_ = compiler.major_;
1420 detail::compiler.minor_ = compiler.minor_;
1421}
1422
1423namespace detail {
1424
1425// Processes special opt flags.
1426// Returns true if the key is a special opt flag.
1427inline bool process_special_opt_flags(std::string &key) {
1428 // Checks for gen::CPP=17|20|23
1429 if (key.find("tgen::CPP:") == 0) {
1430 size_t prefix_len = std::string("tgen::CPP:").size();
1431 tgen_ensure(key.size() == prefix_len + 2 and
1432 std::isdigit(key[prefix_len]) and
1433 std::isdigit(key[prefix_len + 1]),
1434 "invalid CPP format");
1435 int version = std::stoi(key.substr(prefix_len, 2));
1436 set_cpp_version(version);
1437 return true;
1438 }
1439
1440 // Checks for tgen::(GCC|CLANG) or
1441 // tgen::(GCC|CLANG):(version|version.minor).
1442 compiler_kind kind;
1443 size_t prefix_len = 0;
1444
1445 if (key.find("tgen::GCC") == 0) {
1446 kind = compiler_kind::gcc;
1447 prefix_len = std::string("tgen::GCC").size();
1448 } else if (key.find("tgen::CLANG") == 0) {
1449 kind = compiler_kind::clang;
1450 prefix_len = std::string("tgen::CLANG").size();
1451 } else {
1452 return false;
1453 }
1454
1455 if (key.size() == prefix_len) {
1456 set_compiler(compiler_value(kind, 0, 0));
1457 return true;
1458 }
1459
1460 tgen_ensure(key[prefix_len] == ':', "invalid compiler format");
1461 ++prefix_len; // for ':'.
1462
1463 std::string inside = key.substr(prefix_len, key.size() - prefix_len);
1464 int major = 0, minor = 0;
1465
1466 size_t dot = inside.find('.');
1467 if (dot == std::string::npos) {
1468 tgen_ensure(!inside.empty() and
1469 std::all_of(inside.begin(), inside.end(), ::isdigit),
1470 "invalid compiler version");
1471 major = std::stoi(inside);
1472 } else {
1473 std::string maj = inside.substr(0, dot);
1474 std::string min = inside.substr(dot + 1);
1475
1476 tgen_ensure(!maj.empty() and
1477 std::all_of(maj.begin(), maj.end(), ::isdigit) and
1478 maj.size() <= 3,
1479 "invalid compiler major version");
1480 tgen_ensure(!min.empty() and
1481 std::all_of(min.begin(), min.end(), ::isdigit) and
1482 min.size() <= 3,
1483 "invalid compiler minor version");
1484
1485 major = std::stoi(maj);
1486 minor = std::stoi(min);
1487 }
1488
1489 set_compiler(compiler_value(kind, major, minor));
1490
1491 return true;
1492}
1493
1494inline std::vector<std::string>
1495 pos_opts; // Dictionary containing the positional parsed opts.
1496inline std::map<std::string, std::string>
1497 named_opts; // Global dictionary the named parsed opts.
1498
1499template <typename T> T get_opt(const std::string &value) {
1500 try {
1501 size_t consumed = 0;
1502 if constexpr (std::is_same_v<T, bool>) {
1503 if (value == "true" or value == "1")
1504 return true;
1505 if (value == "false" or value == "0")
1506 return false;
1507 } else if constexpr (std::is_integral_v<T>) {
1508 if constexpr (std::is_unsigned_v<T>) {
1509 // stoull accepts a minus sign and wraps; unsigned opts do not.
1510 size_t first = value.find_first_not_of(" \t\n\r\f\v");
1511 if (first != std::string::npos and value[first] != '-') {
1512 auto parsed = std::stoull(value, &consumed);
1513 if (consumed == value.size() and
1514 parsed <= std::numeric_limits<T>::max())
1515 return static_cast<T>(parsed);
1516 }
1517 } else {
1518 auto parsed = std::stoll(value, &consumed);
1519 if (consumed == value.size() and
1520 std::numeric_limits<T>::min() <= parsed and
1521 parsed <= std::numeric_limits<T>::max())
1522 return static_cast<T>(parsed);
1523 }
1524 } else if constexpr (std::is_floating_point_v<T>) {
1525 // stold may reject representable subnormals. Accept a nonzero
1526 // subnormal from strtold, but not overflow or underflow to zero.
1527 char *end;
1528 int saved_errno = errno;
1529 errno = 0;
1530 auto parsed = std::strtold(value.c_str(), &end);
1531 int parse_error = errno;
1532 errno = saved_errno;
1533 bool valid_range =
1534 parse_error == 0 or
1535 (parse_error == ERANGE and parsed != 0 and
1536 std::abs(parsed) < std::numeric_limits<long double>::min());
1537 // Check before narrowing to prevent overflow; preserve explicit
1538 // inf/nan inputs and reject finite nonzero values rounded to zero.
1539 if (end != value.c_str() and end == value.c_str() + value.size() and
1540 valid_range and
1541 (!std::isfinite(parsed) or
1542 (std::numeric_limits<T>::lowest() <= parsed and
1543 parsed <= std::numeric_limits<T>::max()))) {
1544 T result = static_cast<T>(parsed);
1545 if (parsed == 0 or result != 0)
1546 return result;
1547 }
1548 } else
1549 return value; // Default: std::string.
1550 } catch (...) {
1551 }
1552
1553 throw error("invalid value `" + value + "` for type " + typeid(T).name());
1554}
1555
1556inline void parse_opts(int argc, char **argv) {
1557 // Parses the opts into `pos_opts` vector and `named_opts`
1558 // map. Starting from 1 to ignore the name of the executable.
1559 for (int i = 1; i < argc; ++i) {
1560 std::string key(argv[i]);
1561
1562 if (process_special_opt_flags(key))
1563 continue;
1564
1565 if (key[0] == '-') {
1566 tgen_ensure(key.size() > 1,
1567 "invalid opt (" + std::string(argv[i]) + ")");
1568 if ('0' <= key[1] and key[1] <= '9') {
1569 // This case is a positional negative number argument.
1570 pos_opts.push_back(key);
1571 continue;
1572 }
1573
1574 // Pops first char '-'.
1575 key = key.substr(1);
1576 } else {
1577 // This case is a positional argument that does not start with '-'.
1578 pos_opts.push_back(key);
1579 continue;
1580 }
1581
1582 // Pops a possible second char '-'.
1583 if (key[0] == '-') {
1584 tgen_ensure(key.size() > 1,
1585 "invalid opt (" + std::string(argv[i]) + ")");
1586
1587 // Pops first char '-'.
1588 key = key.substr(1);
1589 }
1590
1591 // Assumes that, if it starts with '-' and second char is not a digit,
1592 // then it is a <key, value> pair.
1593 // 1 or 2 chars '-' have already been popped.
1594
1595 std::size_t eq = key.find('=');
1596 if (eq != std::string::npos) {
1597 // This is the '--key=value' case.
1598 std::string value = key.substr(eq + 1);
1599 key = key.substr(0, eq);
1600 tgen_ensure(!key.empty() and !value.empty(),
1601 "expected non-empty key/value in opt (" +
1602 std::string(argv[i]) + ")");
1603 tgen_ensure(named_opts.count(key) == 0,
1604 "cannot have repeated keys");
1605 named_opts[key] = value;
1606 } else {
1607 // This is the '--key value' case.
1608 tgen_ensure(named_opts.count(key) == 0,
1609 "cannot have repeated keys");
1610 tgen_ensure(argv[i + 1], "value cannot be empty");
1611 named_opts[key] = std::string(argv[i + 1]);
1612 ++i;
1613 }
1614 }
1615}
1616
1617inline void set_seed(int argc, char **argv) {
1618 std::vector<uint32_t> seed;
1619
1620 // Starting from 1 to ignore the name of the executable.
1621 for (int i = 1; i < argc; ++i) {
1622 // We append the number of chars, and then the list of chars.
1623 size_t size_pos = seed.size();
1624 seed.push_back(0);
1625 for (char *s = argv[i]; *s != '\0'; ++s) {
1626 ++seed[size_pos];
1627 seed.push_back(*s);
1628 }
1629 }
1630 std::seed_seq seq(seed.begin(), seed.end());
1631 rng.seed(seq);
1632}
1633
1634} // namespace detail
1635
1636// Returns true if there is an opt at a given index.
1637inline bool has_opt(std::size_t index) {
1638 detail::ensure_registered();
1639 return index < detail::pos_opts.size();
1640}
1641
1642// Returns true if there is an opt with a given key.
1643inline bool has_opt(const std::string &key) {
1644 detail::ensure_registered();
1645 return detail::named_opts.count(key) != 0;
1646}
1647template <typename K>
1648std::enable_if_t<std::is_same_v<K, char>, bool> has_opt(K key) {
1649 return has_opt(std::string(1, key));
1650}
1651
1652// Returns the parsed opt by a given index. If no opts with the given index are
1653// found, returns the given default_value.
1654template <typename T>
1655T opt(size_t index, std::optional<T> default_value = std::nullopt) {
1656 detail::ensure_registered();
1657 if (!has_opt(index)) {
1658 if (default_value)
1659 return *default_value;
1660 throw detail::error("cannot find opt at index " +
1661 std::to_string(index));
1662 }
1663 return detail::get_opt<T>(detail::pos_opts[index]);
1664}
1665
1666// Returns the parsed opt by a given key. If no opts with the given key are
1667// found, returns the given default_value.
1668template <typename T>
1669T opt(const std::string &key, std::optional<T> default_value = std::nullopt) {
1670 detail::ensure_registered();
1671 if (!has_opt(key)) {
1672 if (default_value)
1673 return *default_value;
1674 throw detail::error("cannot find opt with key " + key);
1675 }
1676 return detail::get_opt<T>(detail::named_opts[key]);
1677}
1678template <typename T, typename K>
1679std::enable_if_t<std::is_same_v<K, char>, T>
1680opt(K key, std::optional<T> default_value = std::nullopt) {
1681 return opt<T>(std::string(1, key), default_value);
1682}
1683
1684// Registers generator by initializing rng and parsing opts.
1685inline void register_gen(int argc, char **argv) {
1686 detail::set_seed(argc, argv);
1687
1688 detail::pos_opts.clear();
1689 detail::named_opts.clear();
1690 detail::parse_opts(argc, argv);
1691
1692 detail::registered = true;
1693}
1694
1695// Registers generator by initializing rng with a given seed.
1696inline void register_gen(std::optional<long long> seed = std::nullopt) {
1697 if (seed)
1698 detail::rng.seed(*seed);
1699 else
1700 detail::rng.seed();
1701
1702 detail::pos_opts.clear();
1703 detail::named_opts.clear();
1704
1705 detail::registered = true;
1706}
1707
1708/************
1709 * *
1710 * LIST *
1711 * *
1712 ************/
1713
1714/*
1715 * List generator.
1716 *
1717 * List of integral types.
1718 */
1719
1720template <typename T> struct list : gen_base<list<T>> {
1721 // Small integral types cannot hold every index in their own value set.
1722 using range_type =
1723 std::conditional_t<std::is_integral_v<T> and (sizeof(T) < sizeof(int)),
1724 int, T>;
1725 int size_; // Size of list.
1726 range_type value_l_, value_r_; // Range of defined values.
1727 std::set<T> values_; // Set of values. If empty, use range; if not,
1728 // represents the possible values, and the range
1729 // represents the index in this set.
1730 std::map<T, int>
1731 value_idx_in_set_; // Index of every value in the set above.
1732 mutable std::vector<std::pair<range_type, range_type>>
1733 val_range_; // Range of values of each index.
1734 mutable std::vector<std::vector<int>> neigh_; // Adjacency list of equality.
1735 std::vector<std::set<int>>
1736 diff_restrictions_; // All different restrictions.
1737 bool index_constraints_{
1738 false}; // True after fix/equal narrows per-index generation.
1739 mutable bool uses_full_range_{
1740 false}; // If true, every index uses [value_l_, value_r_] lazily.
1741
1742 // Creates generator for lists of size 'size', with random T in [value_left,
1743 // value_right].
1744 list(int size, T value_left, T value_right)
1745 : size_(size), value_l_(value_left), value_r_(value_right),
1746 uses_full_range_(true) {
1747 tgen_ensure(size_ > 0, "list: size must be positive");
1748 tgen_ensure(value_l_ <= value_r_, "list: value range must be valid");
1749 }
1750
1751 // Creates list with value set.
1752 list(int size, std::set<T> values)
1753 : size_(size), values_(values), index_constraints_(true) {
1754 tgen_ensure(size_ > 0, "list: size must be positive");
1755 tgen_ensure(!values.empty(), "list: value set must be non-empty");
1756 value_l_ = 0, value_r_ = static_cast<range_type>(values.size() - 1);
1757 val_range_.assign(size_, {value_l_, value_r_});
1758 int idx = 0;
1759 for (T val : values_)
1760 value_idx_in_set_[val] = idx++;
1761 }
1762
1763 // Restricts lists for list[idx] = val.
1764 list &fix(int idx, T val) {
1765 tgen_ensure(0 <= idx and idx < size_, "list: index must be valid");
1766 ensure_val_range_materialized();
1767 if (values_.size() == 0) {
1768 auto &[left, right] = val_range_[idx];
1769 if (left == right and value_l_ != value_r_) {
1770 tgen_ensure(left == val,
1771 "list: must not set to two different values");
1772 } else {
1773 tgen_ensure(left <= val and val <= right,
1774 "list: value must be in the defined range");
1775 }
1776 left = right = val;
1777 } else {
1778 tgen_ensure(values_.count(val),
1779 "list: value must be in the set of values");
1780 auto &[left, right] = val_range_[idx];
1781 range_type new_val =
1782 static_cast<range_type>(value_idx_in_set_[val]);
1783 tgen_ensure(left <= new_val and new_val <= right,
1784 "list: must not set to two different values");
1785 left = right = new_val;
1786 }
1787 index_constraints_ = true;
1788 return *this;
1789 }
1790
1791 // Restricts lists for list[idx_1] = list[idx_2].
1792 list &equal(int idx_1, int idx_2) {
1793 tgen_ensure(0 <= std::min(idx_1, idx_2) and
1794 std::max(idx_1, idx_2) < size_,
1795 "list: indices must be valid");
1796 if (idx_1 == idx_2)
1797 return *this;
1798
1799 ensure_val_range_materialized();
1800 ensure_neigh_allocated();
1801 index_constraints_ = true;
1802 neigh_[idx_1].push_back(idx_2);
1803 neigh_[idx_2].push_back(idx_1);
1804 return *this;
1805 }
1806
1807 // Restricts lists for list[S] to be equal, for given subset S of indices.
1808 list &equal(std::set<int> indices) {
1809 if (!indices.empty()) {
1810 tgen_ensure(0 <= *indices.begin() and *indices.rbegin() < size_,
1811 "list: indices must be valid");
1812 std::set<int>::iterator beg = indices.begin();
1813 for (auto it = std::next(beg); it != indices.end(); ++it)
1814 equal(*beg, *it);
1815 }
1816 return *this;
1817 }
1818
1819 // Restricts lists for list[left..right] to have all equal values.
1820 list &equal_range(int left, int right) {
1821 tgen_ensure(0 <= left and left <= right and right < size_,
1822 "list: range indices must be valid");
1823 for (int i = left; i < right; ++i)
1824 equal(i, i + 1);
1825 return *this;
1826 }
1827
1828 // Restricts lists for all equal elements.
1829 list &all_equal() { return equal_range(0, size_ - 1); }
1830
1831 // Restricts lists for list[S] to be different (distinct), for given subset
1832 // S of indices. You cannot add two of these restrictions on sets that
1833 // intersect.
1834 list &different(std::set<int> indices) {
1835 if (!indices.empty()) {
1836 tgen_ensure(0 <= *indices.begin() and *indices.rbegin() < size_,
1837 "list: indices must be valid");
1838 diff_restrictions_.push_back(indices);
1839 }
1840 return *this;
1841 }
1842
1843 // Restricts lists for list[idx_1] != list[idx_2].
1844 list &different(int idx_1, int idx_2) {
1845 std::set<int> indices = {idx_1, idx_2};
1846 return different(indices);
1847 }
1848
1849 // Restricts lists for list[left..right] to have all different values.
1850 list &different_range(int left, int right) {
1851 tgen_ensure(0 <= left and left <= right and right < size_,
1852 "list: range indices must be valid");
1853 std::vector<int> indices(right - left + 1);
1854 std::iota(indices.begin(), indices.end(), left);
1855 return different(std::set<int>(indices.begin(), indices.end()));
1856 }
1857
1858 // Restricts lists for all different elements.
1860 std::vector<int> indices(size_);
1861 std::iota(indices.begin(), indices.end(), 0);
1862 return different(std::set<int>(indices.begin(), indices.end()));
1863 }
1864
1865 // Restricts adjacent list entries to be different: list[i] != list[i+1].
1867 for (int i = 1; i < size_; ++i)
1868 different(i - 1, i);
1869 return *this;
1870 }
1871
1872 // List value.
1873 // Operations on a value are not random.
1875 using tgen_is_sequential_tag = detail::is_sequential_tag;
1876
1877 using value_type = T; // Value type, for templates.
1878 using std_type = std::vector<T>; // std type for value.
1879
1880 std::vector<T> vec_; // list.
1881 char sep_; // Separator for printing.
1882
1883 value(const std::vector<T> &vec) : vec_(vec), sep_(' ') {}
1884 value(std::vector<T> &&vec) : vec_(std::move(vec)), sep_(' ') {}
1885 value(const std::initializer_list<T> &il) : value(std::vector<T>(il)) {}
1886
1887 // Fetches size.
1888 int size() const { return static_cast<int>(vec_.size()); }
1889
1890 // Fetches position idx.
1891 T &operator[](int idx) {
1892 tgen_ensure(0 <= idx and idx < size(),
1893 "list: value: index out of bounds");
1894 return vec_[idx];
1895 }
1896 const T &operator[](int idx) const {
1897 tgen_ensure(0 <= idx and idx < size(),
1898 "list: value: index out of bounds");
1899 return vec_[idx];
1900 }
1901
1902 // Sorts values in non-decreasing order.
1903 // O(n log n).
1905 std::sort(vec_.begin(), vec_.end());
1906 return *this;
1907 }
1908
1909 // Reverses list.
1910 // O(n).
1912 std::reverse(vec_.begin(), vec_.end());
1913 return *this;
1914 }
1915
1916 // Sets the separator for the list, for printing.
1917 // O(1).
1918 value &separator(char sep) {
1919 sep_ = sep;
1920 return *this;
1921 }
1922
1923 // Concatenates two values.
1924 // Linear.
1925 value operator+(const value &rhs) const {
1926 std::vector<T> new_vec = vec_;
1927 for (int i = 0; i < rhs.size(); ++i)
1928 new_vec.push_back(rhs[i]);
1929 return value(new_vec);
1930 }
1931
1932 // Shuffles list uniformly.
1933 // O(n).
1935 tgen::shuffle(vec_.begin(), vec_.end());
1936 return *this;
1937 }
1938
1939 // Returns a random element uniformly.
1940 // O(1).
1941 T pick() const { return vec_[next<int>(0, size() - 1)]; }
1942
1943 // Returns vec_[i] with probability proportional to distribution[i].
1944 // O(1).
1945 template <typename Dist>
1946 T pick_by_distribution(const std::vector<Dist> &distribution) const {
1947 tgen_ensure(static_cast<size_t>(size()) == distribution.size(),
1948 "value and distribution must have the same size");
1949 return vec_[next_by_distribution(distribution)];
1950 }
1951 template <typename Dist>
1952 T pick_by_distribution(
1953 const std::initializer_list<Dist> &distribution) const {
1954 return pick_by_distribution(std::vector<Dist>(distribution));
1955 }
1956
1957 // Chooses k values uniformly, as in a subsequence of size k.
1958 // O(n).
1959 value choose(int k) const {
1960 tgen_ensure(0 < k and k <= size(),
1961 "number of elements to choose must be valid");
1962 std::vector<T> new_vec;
1963 int need = k;
1964 for (int i = 0; need > 0; ++i) {
1965 int left = size() - i;
1966 if (next(1, left) <= need) {
1967 new_vec.push_back(vec_[i]);
1968 need--;
1969 }
1970 }
1971 return value(new_vec);
1972 }
1973
1974 // Prints to std::ostream, separated by sep_.
1975 friend std::ostream &operator<<(std::ostream &out, const value &val) {
1976 for (int i = 0; i < val.size(); ++i) {
1977 if (i > 0)
1978 out << val.sep_;
1979 out << val[i];
1980 }
1981 return out;
1982 }
1983
1984 // Gets a std::vector representing the value.
1985 auto to_std() const {
1986 if constexpr (!detail::is_generator_value<T>::value) {
1987 return vec_;
1988 } else {
1989 std::vector<typename T::std_type> vec;
1990 for (const auto &i : vec_)
1991 vec.push_back(i.to_std());
1992 return vec;
1993 }
1994 }
1995 };
1996
1997 // Generates list value.
1998 // Optimized for performance (unconstrained and all-different fast paths).
1999 // O(n log n).
2000 value gen() const {
2001 if (diff_restrictions_.empty()) {
2002 if (auto unconstrained = try_gen_unconstrained())
2003 return *unconstrained;
2004 }
2005 if (auto all_different = try_gen_all_different())
2006 return *all_different;
2007
2008 ensure_neigh_allocated();
2009 std::vector<range_type> vec(size_);
2010 std::vector<bool> defined_idx(
2011 size_, false); // For every index, if it has been set in `vec`.
2012
2013 std::vector<int> comp_id(size_, -1); // Component id of each index.
2014 std::vector<std::vector<int>> comp(size_); // Component of each comp-id.
2015 int comp_count = 0; // Number of different components.
2016
2017 // Defines value of entire component.
2018 auto define_comp = [&](int cur_comp, range_type val) {
2019 for (int idx : comp[cur_comp]) {
2020 tgen_ensure(!defined_idx[idx]);
2021 vec[idx] = val;
2022 defined_idx[idx] = true;
2023 }
2024 };
2025
2026 // Groups = components.
2027 {
2028 std::vector<bool> vis(size_, false); // Visited for each index.
2029 for (int idx = 0; idx < size_; ++idx)
2030 if (!vis[idx]) {
2031 range_type new_value;
2032 bool value_defined = false;
2033
2034 // BFS to visit the connected component, grouping equal
2035 // values.
2036 std::queue<int> q({idx});
2037 vis[idx] = true;
2038 std::vector<int> component;
2039 while (!q.empty()) {
2040 int cur_idx = q.front();
2041 q.pop();
2042
2043 component.push_back(cur_idx);
2044
2045 // Checks value.
2046 auto [l, r] = val_range_at(cur_idx);
2047 if (l == r) {
2048 if (!value_defined) {
2049 // We found the value.
2050 value_defined = true;
2051 new_value = l;
2052 } else if (new_value != l) {
2053 // We found a contradiction
2054 throw detail::contradiction_error(
2055 "list",
2056 "tried to set value to `" +
2057 std::to_string(new_value) +
2058 "`, but it was already set as `" +
2059 std::to_string(l) + "`");
2060 }
2061 }
2062
2063 for (int nxt_idx : neigh_[cur_idx]) {
2064 if (!vis[nxt_idx]) {
2065 vis[nxt_idx] = true;
2066 q.push(nxt_idx);
2067 }
2068 }
2069 }
2070
2071 // Group entire component, checking if value is defined.
2072 for (int cur_idx : component) {
2073 comp_id[cur_idx] = comp_count;
2074 comp[comp_id[cur_idx]].push_back(cur_idx);
2075 }
2076
2077 // Defines value if needed.
2078 if (value_defined)
2079 define_comp(comp_count, new_value);
2080
2081 ++comp_count;
2082 }
2083 }
2084
2085 // Initial parsing of different restrictions.
2086 std::vector<std::set<int>> diff_containing_comp_idx(comp_count);
2087 {
2088 int dist_id = 0;
2089 for (const std::set<int> &diff : diff_restrictions_) {
2090 // Checks if there are too many different values.
2091 if (detail::i128(diff.size()) > range_cardinality())
2092 throw detail::contradiction_error(
2093 "list",
2094 "tried to generate " + std::to_string(diff.size()) +
2095 " different values, but the maximum is " +
2096 std::to_string(
2097 static_cast<uint64_t>(range_cardinality())));
2098
2099 // Checks if two values in same component are marked as
2100 // different.
2101 std::set<int> comp_ids;
2102 for (int idx : diff) {
2103 if (comp_ids.count(comp_id[idx]))
2104 throw detail::contradiction_error(
2105 "list", "tried to set two indices as equal and "
2106 "different");
2107 comp_ids.insert(comp_id[idx]);
2108
2109 diff_containing_comp_idx[comp_id[idx]].insert(dist_id);
2110 }
2111 ++dist_id;
2112 }
2113 }
2114
2115 // If some value is in >= 3 sets, then there is a cycle.
2116 for (auto &diff_containing : diff_containing_comp_idx)
2117 if (diff_containing.size() >= 3)
2118 throw detail::complex_restrictions_error(
2119 "list",
2120 "one index cannot be in >= 3 'different' restrictions");
2121
2122 std::vector<bool> vis_diff(diff_restrictions_.size(), false);
2123 std::vector<bool> initially_defined_comp_idx(comp_count, false);
2124
2125 // Fills the value in a tree defined by "different" restrictions.
2126 auto define_tree = [&](int diff_id) {
2127 // The set `diff_restrictions_[diff_id]` can have some
2128 // values that are defined.
2129
2130 // Generates set of already defined values.
2131 std::set<range_type> defined_values;
2132 for (int idx : diff_restrictions_[diff_id])
2133 if (defined_idx[idx]) {
2134 // Checks if two values in `diff_restrictions_[dist_id]`
2135 // have been set to the same value
2136 if (defined_values.count(vec[idx]))
2137 throw detail::contradiction_error(
2138 "list",
2139 "tried to set two indices as equal and different");
2140
2141 defined_values.insert(vec[idx]);
2142 }
2143
2144 // Generates values in this root "different" restriction.
2145 {
2146 int new_value_count =
2147 static_cast<int>(diff_restrictions_[diff_id].size()) -
2148 static_cast<int>(defined_values.size());
2149 std::vector<range_type> generated_values =
2150 generate_distinct_values(new_value_count, defined_values);
2151 auto val_it = generated_values.begin();
2152 for (int idx : diff_restrictions_[diff_id])
2153 if (defined_idx[idx]) {
2154 // The root can cover these components, but there should
2155 // not be any other defined in this tree.
2156 initially_defined_comp_idx[comp_id[idx]] = false;
2157 } else {
2158 define_comp(comp_id[idx], *val_it);
2159 ++val_it;
2160 }
2161 }
2162
2163 // BFS on the tree of "different" restrictions.
2164 std::queue<std::pair<int, int>> q; // {id, parent id}
2165 q.emplace(diff_id, -1);
2166 vis_diff[diff_id] = true;
2167 while (!q.empty()) {
2168 auto [cur_diff, parent] = q.front();
2169 q.pop();
2170
2171 std::set<int> neigh_diff;
2172 for (int idx : diff_restrictions_[cur_diff])
2173 for (int nxt_diff :
2174 diff_containing_comp_idx[comp_id[idx]]) {
2175 if (nxt_diff == cur_diff or nxt_diff == parent)
2176 continue;
2177
2178 // Cycle found.
2179 if (vis_diff[nxt_diff])
2180 throw detail::complex_restrictions_error(
2181 "list",
2182 "cycle found in 'different' restrictions");
2183
2184 neigh_diff.insert(nxt_diff);
2185 }
2186
2187 for (int nxt_diff : neigh_diff) {
2188 vis_diff[nxt_diff] = true;
2189 q.emplace(nxt_diff, cur_diff);
2190
2191 // Generates this "different" restriction.
2192 std::set<range_type> nxt_defined_values;
2193 for (int idx2 : diff_restrictions_[nxt_diff])
2194 if (defined_idx[idx2]) {
2195 // There cannot be any more defined. This case is
2196 // when there are values not covered by a single
2197 // "different" restriction in the tree.
2198 if (initially_defined_comp_idx[comp_id[idx2]])
2199 throw detail::complex_restrictions_error(
2200 "list");
2201
2202 nxt_defined_values.insert(vec[idx2]);
2203 }
2204 int new_value_count =
2205 static_cast<int>(diff_restrictions_[nxt_diff].size()) -
2206 static_cast<int>(nxt_defined_values.size());
2207 std::vector<range_type> generated_values =
2208 generate_distinct_values(new_value_count,
2209 nxt_defined_values);
2210 auto val_it = generated_values.begin();
2211 for (int idx2 : diff_restrictions_[nxt_diff])
2212 if (!defined_idx[idx2]) {
2213 define_comp(comp_id[idx2], *val_it);
2214 ++val_it;
2215 }
2216 }
2217 }
2218 };
2219
2220 // Loops through "different" restrictions, sorts "different"
2221 // restrictions by number of defined components (non-increasing). This
2222 // guarantees that if there is a valid root (that covers all 'defined'),
2223 // we find it.
2224 {
2225 std::vector<std::pair<int, int>> defined_cnt_and_diff_idx;
2226 int dist_id = 0;
2227 for (const std::set<int> &diff : diff_restrictions_) {
2228 int defined_cnt = 0;
2229 for (int idx : diff)
2230 if (defined_idx[idx]) {
2231 ++defined_cnt;
2232 initially_defined_comp_idx[comp_id[idx]] = true;
2233 }
2234 defined_cnt_and_diff_idx.emplace_back(defined_cnt, dist_id);
2235 ++dist_id;
2236 }
2237
2238 std::sort(defined_cnt_and_diff_idx.rbegin(),
2239 defined_cnt_and_diff_idx.rend());
2240 for (auto [defined_cnt, diff_idx] : defined_cnt_and_diff_idx)
2241 if (!vis_diff[diff_idx])
2242 define_tree(diff_idx);
2243 }
2244
2245 // Loops through "different" restrictions do define the rest.
2246 for (std::size_t dist_id = 0; dist_id < diff_restrictions_.size();
2247 ++dist_id)
2248 if (!vis_diff[dist_id])
2249 define_tree(static_cast<int>(dist_id));
2250
2251 // Define final values. These values all should be random in [l, r], and
2252 // the "different" restrictions have already been processed. However,
2253 // there can be still equality restrictions, so we define entire
2254 // components.
2255 for (int idx = 0; idx < size_; ++idx)
2256 if (!defined_idx[idx])
2257 define_comp(comp_id[idx], next<range_type>(value_l_, value_r_));
2258
2259 if (!values_.empty()) {
2260 // Needs to fetch the values from the value set.
2261 std::vector<range_type> value_vec(values_.begin(), values_.end());
2262 for (range_type &val : vec)
2263 val = value_vec[val];
2264 }
2265
2266 if constexpr (std::is_same_v<range_type, T>)
2267 return value(std::move(vec));
2268 else
2269 return value(std::vector<T>(vec.begin(), vec.end()));
2270 }
2271
2272 private:
2273 detail::i128 range_cardinality() const {
2274 // Promote before subtraction: the full 64-bit domain has 2^64 values.
2275 return detail::i128(value_r_) - detail::i128(value_l_) + 1;
2276 }
2277 // Materializes neigh_ after the first equality restriction.
2278 void ensure_neigh_allocated() const {
2279 if (neigh_.size() == static_cast<size_t>(size_))
2280 return;
2281 neigh_.assign(size_, {});
2282 }
2283
2284 // Materializes val_range_ after the first per-index restriction.
2285 void ensure_val_range_materialized() const {
2286 if (!uses_full_range_)
2287 return;
2288 val_range_.assign(size_, {value_l_, value_r_});
2289 uses_full_range_ = false;
2290 }
2291
2292 // Returns the allowed value range at index idx.
2293 std::pair<range_type, range_type> val_range_at(int idx) const {
2294 if (uses_full_range_)
2295 return {value_l_, value_r_};
2296 return val_range_[idx];
2297 }
2298
2299 // Generates a uniformly random list of k distinct values in `[value_l,
2300 // value_r]`, such that no value is in `forbidden_values`.
2301 std::vector<range_type> generate_distinct_values(
2302 int k, const std::set<range_type> &forbidden_values) const {
2303 for (auto forbidden : forbidden_values)
2304 tgen_ensure(value_l_ <= forbidden and forbidden <= value_r_);
2305 const detail::i128 available =
2306 range_cardinality() - forbidden_values.size();
2307 if (available < k)
2308 throw detail::complex_restrictions_error(
2309 "list", "not enough distinct values");
2310 if (k == 0)
2311 return {};
2312 if (forbidden_values.empty())
2313 return distinct_range<range_type>(value_l_, value_r_)
2314 .gen_list(k)
2315 .to_std();
2316
2317 // Rank offsets may exceed T even when every resulting value fits T.
2318 // Subtracting at least one forbidden value makes the count fit
2319 // uint64_t.
2320 const uint64_t count = static_cast<uint64_t>(available);
2321 std::map<uint64_t, uint64_t> virtual_list;
2322 std::vector<std::pair<uint64_t, int>> ranks;
2323 ranks.reserve(static_cast<size_t>(k));
2324 for (int i = 0; i < k; ++i) {
2325 uint64_t index = static_cast<uint64_t>(i);
2326 uint64_t j = next<uint64_t>(index, count - 1);
2327 uint64_t vj = virtual_list.count(j) ? virtual_list[j] : j;
2328 uint64_t vi =
2329 virtual_list.count(index) ? virtual_list[index] : index;
2330 virtual_list[j] = vi;
2331 ranks.emplace_back(vj, i);
2332 }
2333 // Map allowed-value ranks back to coordinates in one ordered sweep.
2334 std::sort(ranks.begin(), ranks.end());
2335 std::vector<range_type> result(static_cast<size_t>(k));
2336 auto forbidden = forbidden_values.begin();
2337 detail::i128 skipped = 0;
2338 for (auto [rank, index] : ranks) {
2339 // Widen before adding offsets to avoid signed overflow.
2340 detail::i128 chosen = detail::i128(value_l_) + rank + skipped;
2341 while (forbidden != forbidden_values.end() and
2342 *forbidden <= chosen) {
2343 ++forbidden;
2344 ++skipped;
2345 ++chosen;
2346 }
2347 result[index] = static_cast<range_type>(chosen);
2348 }
2349 return result;
2350 }
2351
2352 // If this generator has no constraints beyond [value_l_, value_r_],
2353 // returns independent uniform samples; otherwise returns std::nullopt.
2354 // O(n).
2355 std::optional<value> try_gen_unconstrained() const {
2356 if (!values_.empty() or index_constraints_)
2357 return std::nullopt;
2358
2359 std::vector<T> vec(size_);
2360 for (int i = 0; i < size_; ++i)
2361 vec[i] =
2362 next<T>(static_cast<T>(value_l_), static_cast<T>(value_r_));
2363 return value(vec);
2364 }
2365
2366 // If this generator is exactly all-distinct in [value_l_, value_r_],
2367 // returns a uniformly random list; otherwise returns std::nullopt.
2368 // Optimized for performance (distinct_range fast path).
2369 // O(n log n).
2370 std::optional<value> try_gen_all_different() const {
2371 if (!values_.empty() or diff_restrictions_.size() != 1)
2372 return std::nullopt;
2373
2374 const std::set<int> &diff = diff_restrictions_[0];
2375 if (static_cast<int>(diff.size()) != size_ or *diff.begin() != 0 or
2376 *diff.rbegin() != size_ - 1)
2377 return std::nullopt;
2378
2379 if (!neigh_.empty()) {
2380 for (const auto &adj : neigh_) {
2381 if (!adj.empty())
2382 return std::nullopt;
2383 }
2384 }
2385
2386 if (index_constraints_)
2387 return std::nullopt;
2388
2389 if (detail::i128(size_) > range_cardinality())
2390 throw detail::contradiction_error(
2391 "list",
2392 "tried to generate " + std::to_string(size_) +
2393 " different values, but the maximum is " +
2394 std::to_string(static_cast<uint64_t>(range_cardinality())));
2395
2396 return distinct_range<T>(static_cast<T>(value_l_),
2397 static_cast<T>(value_r_))
2398 .gen_list(size_);
2399 }
2400};
2401
2402/*******************
2403 * *
2404 * PERMUTATION *
2405 * *
2406 *******************/
2407
2408/*
2409 * Permutation generation.
2410 *
2411 * Permutation are defined always as numbers in [0, n), that is, 0-based.
2412 */
2413
2415 int size_; // Size of permutation.
2416 std::vector<std::pair<int, int>> defs_; // {idx, value}.
2417 std::optional<std::vector<int>> cycle_sizes_; // Cycle sizes.
2418
2419 // Creates generator for permutation of size 'size'.
2420 permutation(int size) : size_(size) {
2421 tgen_ensure(size_ > 0, "permutation: size must be positive");
2422 }
2423
2424 // Restricts permutations for permutation[idx] = val.
2425 permutation &fix(int idx, int val) {
2426 tgen_ensure(0 <= idx and idx < size_,
2427 "permutation: index must be valid");
2428 defs_.emplace_back(idx, val);
2429 return *this;
2430 }
2431
2432 // Restricts permutations for permutation to have cycle sizes.
2433 permutation &cycles(const std::vector<int> &cycle_sizes) {
2434 // Subtract from the remaining size instead of summing to avoid
2435 // overflow.
2436 int remaining = size_;
2437 for (int cycle_size : cycle_sizes) {
2438 tgen_ensure(cycle_size > 0,
2439 "permutation: cycle sizes must be positive");
2441 cycle_size <= remaining,
2442 "permutation: cycle sizes must add up to size of permutation");
2443 remaining -= cycle_size;
2444 }
2446 remaining == 0,
2447 "permutation: cycle sizes must add up to size of permutation");
2448 cycle_sizes_ = cycle_sizes;
2449 return *this;
2450 }
2451 permutation &cycles(const std::initializer_list<int> &cycle_sizes) {
2452 return cycles(std::vector<int>(cycle_sizes));
2453 }
2454
2455 // Permutation value.
2456 // Operations on a value are not random.
2458 using tgen_is_sequential_tag = detail::is_sequential_tag;
2459
2460 using std_type = std::vector<int>; // std type for value.
2461 std::vector<int> vec_; // Permutation.
2462 char sep_; // Separator for printing.
2463 bool print_1_based_; // If should print values 1-based (print only).
2464
2465 value(const std::vector<int> &vec)
2466 : vec_(vec), sep_(' '), print_1_based_(false) {
2467 tgen_ensure(!vec_.empty(), "permutation: value: cannot be empty");
2468 std::vector<bool> vis(vec_.size(), false);
2469 for (int i = 0; i < size(); ++i) {
2470 tgen_ensure(0 <= vec_[i] and
2471 vec_[i] < static_cast<int>(vec_.size()),
2472 "permutation: value: values must be from `0` to "
2473 "`size-1`");
2474 tgen_ensure(!vis[vec_[i]],
2475 "permutation: value: cannot have repeated values");
2476 vis[vec_[i]] = true;
2477 }
2478 }
2479 value(const std::initializer_list<int> &il)
2480 : value(std::vector<int>(il)) {}
2481
2482 // Fetches size.
2483 int size() const { return static_cast<int>(vec_.size()); }
2484
2485 // Fetches position idx.
2486 const int &operator[](int idx) const {
2487 tgen_ensure(0 <= idx and idx < size(),
2488 "permutation: value: index out of bounds");
2489 return vec_[idx];
2490 }
2491
2492 // Returns parity of the permutation (+1 if even, -1 if odd).
2493 // O(n).
2494 int parity() const {
2495 std::vector<bool> vis(size(), false);
2496 int cycles = 0;
2497
2498 for (int i = 0; i < size(); ++i)
2499 if (!vis[i]) {
2500 ++cycles;
2501 for (int j = i; !vis[j]; j = vec_[j])
2502 vis[j] = true;
2503 }
2504 // Even iff (n - cycles) is even.
2505 return ((size() - cycles) % 2 == 0) ? +1 : -1;
2506 }
2507
2508 // Sorts values in increasing order.
2509 // O(n).
2511 for (int i = 0; i < size(); ++i)
2512 vec_[i] = i;
2513 return *this;
2514 }
2515
2516 // Reverses permutation.
2517 // O(n).
2519 std::reverse(vec_.begin(), vec_.end());
2520 return *this;
2521 }
2522
2523 // Inverse of the permutation.
2524 // O(n).
2526 std::vector<int> inv(size());
2527 for (int i = 0; i < size(); ++i)
2528 inv[vec_[i]] = i;
2529 swap(vec_, inv);
2530 return *this;
2531 }
2532
2533 // Sets the separator, for printing.
2534 // O(1).
2535 value &separator(char sep) {
2536 sep_ = sep;
2537 return *this;
2538 }
2539
2540 // Sets that should print values 1-based. Does not change stored
2541 // values or to_std(); use to_std_1_based() for a 1-based export.
2542 // O(1).
2544 print_1_based_ = true;
2545 return *this;
2546 }
2547
2548 // Shuffles permutation uniformly.
2549 // O(n).
2551 tgen::shuffle(vec_.begin(), vec_.end());
2552 return *this;
2553 }
2554
2555 // Returns a random element uniformly.
2556 // O(1).
2557 int pick() const { return vec_[next<int>(0, size() - 1)]; }
2558
2559 // Returns vec_[i] with probability proportional to distribution[i].
2560 // O(1).
2561 template <typename Dist>
2562 int pick_by_distribution(const std::vector<Dist> &distribution) const {
2563 tgen_ensure(static_cast<size_t>(size()) == distribution.size(),
2564 "value and distribution must have the same size");
2565 return vec_[next_by_distribution(distribution)];
2566 }
2567 template <typename Dist>
2568 int pick_by_distribution(
2569 const std::initializer_list<Dist> &distribution) const {
2570 return pick_by_distribution(std::vector<Dist>(distribution));
2571 }
2572
2573 // Prints to std::ostream, separated by sep_.
2574 friend std::ostream &operator<<(std::ostream &out, const value &val) {
2575 for (int i = 0; i < val.size(); ++i) {
2576 if (i > 0)
2577 out << val.sep_;
2578 out << val[i] + val.print_1_based_;
2579 }
2580 return out;
2581 }
2582
2583 // Gets a std::vector representing the value (0-based). Unaffected by
2584 // print_1_based().
2585 std::vector<int> to_std() const { return std_type(vec_); }
2586
2587 // Gets a 1-based std::vector (each element +1). Unaffected by
2588 // print_1_based().
2589 std::vector<int> to_std_1_based() const {
2590 std::vector<int> out = vec_;
2591 for (int &x : out)
2592 ++x;
2593 return out;
2594 }
2595 };
2596
2597 // Generates permutation value.
2598 // O(n).
2599 value gen() const {
2600 // Check here so neither order of fix() and cycles() is ignored.
2602 !cycle_sizes_ or defs_.empty(),
2603 "permutation: fixed values and cycle sizes cannot be combined");
2604 if (!cycle_sizes_) {
2605 // Cycle sizes not specified.
2606 std::vector<int> idx_to_val(size_, -1), val_to_idx(size_, -1);
2607 for (auto [idx, val] : defs_) {
2609 0 <= val and val < size_,
2610 "permutation: value in permutation must be in [0, " +
2611 std::to_string(size_) + ")");
2612
2613 if (idx_to_val[idx] != -1) {
2614 tgen_ensure(idx_to_val[idx] == val,
2615 "permutation: cannot set an index to two "
2616 "different values");
2617 } else
2618 idx_to_val[idx] = val;
2619
2620 if (val_to_idx[val] != -1) {
2621 tgen_ensure(val_to_idx[val] == idx,
2622 "permutation: cannot set two indices to the "
2623 "same value");
2624 } else
2625 val_to_idx[val] = idx;
2626 }
2627
2628 std::vector<int> perm(size_);
2629 std::iota(perm.begin(), perm.end(), 0);
2630 shuffle(perm.begin(), perm.end());
2631 int cur_idx = 0;
2632 for (int &i : idx_to_val)
2633 if (i == -1) {
2634 // While this value is used, skip.
2635 while (val_to_idx[perm[cur_idx]] != -1)
2636 ++cur_idx;
2637 i = perm[cur_idx++];
2638 }
2639 return idx_to_val;
2640 }
2641
2642 // Creates cycles.
2643 std::vector<int> order(size_);
2644 std::iota(order.begin(), order.end(), 0);
2645 shuffle(order.begin(), order.end());
2646 int idx = 0;
2647 std::vector<std::vector<int>> cycles;
2648 for (int cycle_size : *cycle_sizes_) {
2649 cycles.emplace_back();
2650 for (int i = 0; i < cycle_size; ++i)
2651 cycles.back().push_back(order[idx++]);
2652 }
2653
2654 // Retrieves permutation from cycles.
2655 std::vector<int> perm(size_, -1);
2656 for (const std::vector<int> &cycle : cycles) {
2657 int cur_size = static_cast<int>(cycle.size());
2658 for (int i = 0; i < cur_size; ++i)
2659 perm[cycle[i]] = cycle[(i + 1) % cur_size];
2660 }
2661
2662 return value(perm);
2663 }
2664};
2665
2666/************
2667 * *
2668 * MATH *
2669 * *
2670 ************/
2671
2672namespace math {
2673
2674namespace detail {
2675
2676using namespace tgen::detail;
2677
2678inline int popcount(uint64_t x) { return __builtin_popcountll(x); }
2679
2680inline int ctzll(uint64_t x) {
2681 // Mystery code found on the internet.
2682 // Uses de Bruijn sequence.
2683 static const unsigned char index64[64] = {
2684 0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28,
2685 62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11,
2686 63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10,
2687 51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12};
2688 return index64[((x & -x) * 0x022FDD63CC95386D) >> 58];
2689}
2690
2691inline uint64_t mul_mod(uint64_t a, uint64_t b, uint64_t m) {
2692 return static_cast<uint64_t>(static_cast<u128>(a) * b % m);
2693}
2694
2695// O(log n).
2696// 0 <= x < m.
2697inline uint64_t expo_mod(uint64_t x, uint64_t y, uint64_t m) {
2698 if (!y)
2699 return 1;
2700 uint64_t ans = expo_mod(mul_mod(x, x, m), y / 2, m);
2701 return y % 2 ? mul_mod(x, ans, m) : ans;
2702}
2703
2704} // namespace detail
2705
2706// O(log^2 n).
2707inline bool is_prime(uint64_t n) {
2708 if (n < 2)
2709 return false;
2710 if (n == 2 or n == 3)
2711 return true;
2712 if (n % 2 == 0)
2713 return false;
2714
2715 uint64_t r = detail::ctzll(n - 1), d = n >> r;
2716 // These bases are guaranteed to work for n <= 2^64.
2717 for (int a : {2, 325, 9375, 28178, 450775, 9780504, 1795265022}) {
2718 uint64_t x = detail::expo_mod(a, d, n);
2719 if (x == 1 or x == n - 1 or a % n == 0)
2720 continue;
2721
2722 for (uint64_t j = 0; j < r - 1; ++j) {
2723 x = detail::mul_mod(x, x, n);
2724 if (x == n - 1)
2725 break;
2726 }
2727 if (x != n - 1)
2728 return false;
2729 }
2730 return true;
2731}
2732
2733namespace detail {
2734
2735inline uint64_t pollard_rho(uint64_t n) {
2736 if (n == 1 or is_prime(n))
2737 return n;
2738 auto f = [n](uint64_t x) { return mul_mod(x, x, n) + 1; };
2739
2740 uint64_t x = 0, y = 0, t = 30, prd = 2, x0 = 1, q;
2741 while (t % 40 != 0 or std::gcd(prd, n) == 1) {
2742 if (x == y)
2743 x = ++x0, y = f(x);
2744 q = mul_mod(prd, x > y ? x - y : y - x, n);
2745 if (q != 0)
2746 prd = q;
2747 x = f(x), y = f(f(y)), ++t;
2748 }
2749 return std::gcd(prd, n);
2750}
2751
2752inline std::vector<uint64_t> factor(uint64_t n) {
2753 if (n == 1)
2754 return {};
2755 if (is_prime(n))
2756 return {n};
2757 uint64_t d = pollard_rho(n);
2758 std::vector<uint64_t> l = factor(d), r = factor(n / d);
2759 l.insert(l.end(), r.begin(), r.end());
2760 return l;
2761}
2762
2763// Error handling.
2764template <typename T>
2765std::runtime_error there_is_no_in_range_error(const std::string &type, T l,
2766 T r) {
2767 return error("math: there is no " + type + " in range [" +
2768 std::to_string(l) + ", " + std::to_string(r) + "]");
2769}
2770template <typename T>
2771std::runtime_error there_is_no_from_error(const std::string &type, T r) {
2772 return error("math: there is no " + type + " from " + std::to_string(r));
2773}
2774template <typename T>
2775std::runtime_error there_is_no_upto_error(const std::string &type, T r) {
2776 return error("math: there is no " + type + " up to " + std::to_string(r));
2777}
2778
2779// O(log mod).
2780// 0 < a < mod.
2781// gcd(a, mod) = 1.
2782inline i128 modular_inverse_128(i128 a, i128 mod) {
2783 tgen_ensure(0 < a and a < mod,
2784 "math: modular inverse requires 0 < value < mod");
2785
2786 i128 t = 0, new_t = 1;
2787 i128 r = mod, new_r = a;
2788
2789 while (new_r != 0) {
2790 i128 q = r / new_r;
2791
2792 auto tmp_t = t - q * new_t;
2793 t = new_t;
2794 new_t = tmp_t;
2795
2796 auto tmp_r = r - q * new_r;
2797 r = new_r;
2798 new_r = tmp_r;
2799 }
2800
2801 tgen_ensure(r == 1, "math: remainder and mod must be coprime");
2802
2803 if (t < 0)
2804 t += mod;
2805 return t;
2806}
2807
2808// checks if a * b <= limit, for positive numbers.
2809inline bool mul_leq(uint64_t a, uint64_t b, uint64_t limit) {
2810 if (a == 0 or b == 0)
2811 return true;
2812 return a <= limit / b;
2813}
2814
2815// base^exp, or null if base^exp > limit.
2816inline std::optional<uint64_t> expo(uint64_t base, uint64_t exp,
2817 uint64_t limit) {
2818 uint64_t result = 1;
2819
2820 while (exp) {
2821 if (exp & 1) {
2822 if (!mul_leq(result, base, limit))
2823 return std::nullopt;
2824 result *= base;
2825 }
2826
2827 exp >>= 1;
2828 // Necessary for correctness.
2829 if (!exp)
2830 break;
2831
2832 if (!mul_leq(base, base, limit))
2833 return std::nullopt;
2834 base *= base;
2835 }
2836 return result;
2837}
2838
2839// O(log n log k).
2840// 0 < k.
2841inline uint64_t kth_root_floor(uint64_t n, uint64_t k) {
2842 tgen_ensure_against_bug(k > 0, "math: value must be valid");
2843 if (k == 1 or n <= 1)
2844 return n;
2845
2846 uint64_t lo = 1, hi = 1ULL << ((64 + k - 1) / k);
2847
2848 while (lo < hi) {
2849 uint64_t mid = lo + (hi - lo + 1) / 2;
2850
2851 if (expo(mid, k, n)) {
2852 lo = mid;
2853 } else {
2854 hi = mid - 1;
2855 }
2856 }
2857 return lo;
2858}
2859
2860// gcd(a, b).
2861// O(log a).
2862inline i128 gcd128(i128 a, i128 b) {
2863 if (a < 0)
2864 a = -a;
2865 if (b < 0)
2866 b = -b;
2867 while (b != 0) {
2868 i128 t = a % b;
2869 a = b;
2870 b = t;
2871 }
2872 return a;
2873}
2874
2875// min(2^64, a*b).
2876// O(log a).
2877// a, b >= 0.
2878inline i128 mul_saturate(i128 a, i128 b) {
2879 tgen_ensure(a >= 0 and b >= 0);
2880 static const i128 LIMIT = static_cast<i128>(1) << 64;
2881 if (a == 0 or b == 0)
2882 return 0;
2883 if (a > LIMIT / b)
2884 return LIMIT;
2885 return a * b;
2886}
2887
2888struct crt {
2889 using T = i128;
2890 T a, m;
2891
2892 crt() : a(0), m(1) {}
2893 crt(T a_, T m_) : a(a_), m(m_) {}
2894 crt operator*(crt C) {
2895 if (m == 0 or C.m == 0)
2896 return {-1, 0};
2897
2898 T g = gcd128(m, C.m);
2899 if ((C.a - a) % g != 0)
2900 return {-1, 0};
2901
2902 T m1 = m / g;
2903 T m2 = C.m / g;
2904
2905 if (m2 == 1)
2906 return {a, m};
2907
2908 T inv = modular_inverse_128(m1 % m2, m2);
2909
2910 T k = ((C.a - a) / g) % m2;
2911 if (k < 0)
2912 k += m2;
2913
2914 k = static_cast<u128>(k) * inv % m2;
2915
2916 T lcm = mul_saturate(m, m2);
2917
2918 T res = (a + static_cast<T>((static_cast<u128>(k) * m) % lcm)) % lcm;
2919 if (res < 0)
2920 res += lcm;
2921
2922 return {res, lcm};
2923 }
2924};
2925
2926// Math hacks to operate on log space.
2927
2928inline constexpr long double LOG_ZERO = -INFINITY;
2929inline constexpr long double LOG_ONE = 0.0;
2930
2931inline long double log_space(long double x) {
2932 return x == 0.0 ? LOG_ZERO : std::log(x);
2933}
2934
2935// Math hack to add two values in log space.
2936inline long double add_log_space(long double a, long double b) {
2937 if (a < b)
2938 std::swap(a, b);
2939 if (b == LOG_ZERO)
2940 return a;
2941 return a + std::log1p(std::exp(static_cast<double>(b - a)));
2942}
2943
2944// Math hack to subtract two values in log space.
2945// a >= b.
2946inline long double sub_log_space(long double a, long double b) {
2947 if (b >= a)
2948 return LOG_ZERO;
2949 if (b == LOG_ZERO)
2950 return a;
2951 return a + std::log1p(-std::exp(static_cast<double>(b - a)));
2952}
2953
2954} // namespace detail
2955
2956// Sorted.
2957// O(n^(1/4) log n) expected.
2958// 0 < n.
2959inline std::vector<uint64_t> factor(uint64_t n) {
2960 tgen_ensure(n > 0, "math: number to factor must be positive");
2961 auto factors = detail::factor(n);
2962 std::sort(factors.begin(), factors.end());
2963 return factors;
2964}
2965
2966// Sorted.
2967// O(n^(1/4) log n) expected.
2968// 0 < n.
2969inline std::vector<std::pair<uint64_t, int>> factor_by_prime(uint64_t n) {
2970 tgen_ensure(n > 0, "math: number to factor must be positive");
2971 std::vector<std::pair<uint64_t, int>> primes;
2972 for (uint64_t p : factor(n)) {
2973 if (!primes.empty() and primes.back().first == p)
2974 ++primes.back().second;
2975 else
2976 primes.emplace_back(p, 1);
2977 }
2978 return primes;
2979}
2980
2981// O(log mod).
2982// 0 < a < mod.
2983// gcd(a, mod) = 1.
2984inline uint64_t modular_inverse(uint64_t a, uint64_t mod) {
2985 return static_cast<uint64_t>(detail::modular_inverse_128(a, mod));
2986}
2987
2988// O(n^(1/4) log n) expected.
2989// 0 < n.
2990inline uint64_t totient(uint64_t n) {
2991 tgen_ensure(n > 0, "math: totient(0) is undefined");
2992 uint64_t phi = n;
2993
2994 for (auto [p, e] : factor_by_prime(n))
2995 phi -= phi / p;
2996
2997 return phi;
2998}
2999
3000// Returns `(p_i, g_i)`: `p_i` is the prime, `g_i` is the gap.
3001inline const std::pair<std::vector<uint64_t>, std::vector<uint64_t>> &
3002prime_gaps() {
3003 // From https://en.wikipedia.org/wiki/Prime_gap.
3004 static const std::pair<std::vector<uint64_t>, std::vector<uint64_t>> value{
3005 /* clang-format off */ {
3006 2, 3, 7, 23, 89, 113, 523, 887, 1129, 1327, 9551, 15683, 19609,
3007 31397, 155921, 360653, 370261, 492113, 1349533, 1357201, 2010733,
3008 4652353, 17051707, 20831323, 47326693, 122164747, 189695659,
3009 191912783, 387096133, 436273009, 1294268491, 1453168141,
3010 2300942549, 3842610773, 4302407359, 10726904659, 20678048297,
3011 22367084959, 25056082087, 42652618343, 127976334671, 182226896239,
3012 241160624143, 297501075799, 303371455241, 304599508537,
3013 416608695821, 461690510011, 614487453523, 738832927927,
3014 1346294310749, 1408695493609, 1968188556461, 2614941710599,
3015 7177162611713, 13829048559701, 19581334192423, 42842283925351,
3016 90874329411493, 171231342420521, 218209405436543, 1189459969825483,
3017 1686994940955803, 1693182318746371, 43841547845541059,
3018 55350776431903243, 80873624627234849, 203986478517455989,
3019 218034721194214273, 305405826521087869, 352521223451364323,
3020 401429925999153707, 418032645936712127, 804212830686677669,
3021 1425172824437699411, 5733241593241196731, 6787988999657777797
3022 }, /* clang-format on */
3023 {1, 2, 4, 6, 8, 14, 18, 20, 22, 34, 36,
3024 44, 52, 72, 86, 96, 112, 114, 118, 132, 148, 154,
3025 180, 210, 220, 222, 234, 248, 250, 282, 288, 292, 320,
3026 336, 354, 382, 384, 394, 456, 464, 468, 474, 486, 490,
3027 500, 514, 516, 532, 534, 540, 582, 588, 602, 652, 674,
3028 716, 766, 778, 804, 806, 906, 916, 924, 1132, 1184, 1198,
3029 1220, 1224, 1248, 1272, 1328, 1356, 1370, 1442, 1476, 1488, 1510}};
3030
3031 return value;
3032}
3033
3034// Returns pair (first_composite_in_gap, last_composite_in_gap).
3035// O(log(right)) approximately.
3036inline std::pair<uint64_t, uint64_t> prime_gap_upto(uint64_t right) {
3037 if (right < 4)
3038 throw detail::there_is_no_upto_error("prime gap", right);
3039
3040 const auto &[P, G] = prime_gaps();
3041 for (int i = static_cast<int>(P.size()) - 1;; --i) {
3042 if (P[i] >= right)
3043 continue;
3044
3045 uint64_t real_right = std::min(right, P[i] + G[i] - 1);
3046 uint64_t prev = i > 0 ? G[i - 1] : 0;
3047 uint64_t curr = real_right - P[i];
3048
3049 if (curr >= prev)
3050 return {P[i] + 1, real_right};
3051 }
3052}
3053
3054// From https://oeis.org/A002182/b002182.txt.
3056 /* clang-format off */
3057 static const std::vector<uint64_t> highly_composites = {
3058 1, 2, 4, 6, 12, 24, 36, 48, 60, 120, 180, 240, 360, 720, 840, 1260, 1680,
3059 2520, 5040, 7560, 10080, 15120, 20160, 25200, 27720, 45360, 50400, 55440,
3060 83160, 110880, 166320, 221760, 277200, 332640, 498960, 554400, 665280,
3061 720720, 1081080, 1441440, 2162160, 2882880, 3603600, 4324320, 6486480,
3062 7207200, 8648640, 10810800, 14414400, 17297280, 21621600, 32432400,
3063 36756720, 43243200, 61261200, 73513440, 110270160, 122522400, 147026880,
3064 183783600, 245044800, 294053760, 367567200, 551350800, 698377680, 735134400,
3065 1102701600, 1396755360, 2095133040, 2205403200, 2327925600, 2793510720,
3066 3491888400, 4655851200, 5587021440, 6983776800, 10475665200, 13967553600,
3067 20951330400, 27935107200, 41902660800, 48886437600, 64250746560,
3068 73329656400, 80313433200, 97772875200, 128501493120, 146659312800,
3069 160626866400, 240940299600, 293318625600, 321253732800, 481880599200,
3070 642507465600, 963761198400, 1124388064800, 1606268664000, 1686582097200,
3071 1927522396800, 2248776129600, 3212537328000, 3373164194400, 4497552259200,
3072 6746328388800, 8995104518400, 9316358251200, 13492656777600, 18632716502400,
3073 26985313555200, 27949074753600, 32607253879200, 46581791256000,
3074 48910880818800, 55898149507200, 65214507758400, 93163582512000,
3075 97821761637600, 130429015516800, 195643523275200, 260858031033600,
3076 288807105787200, 391287046550400, 577614211574400, 782574093100800,
3077 866421317361600, 1010824870255200, 1444035528936000, 1516237305382800,
3078 1732842634723200, 2021649740510400, 2888071057872000, 3032474610765600,
3079 4043299481020800, 6064949221531200, 8086598962041600, 10108248702552000,
3080 12129898443062400, 18194847664593600, 20216497405104000, 24259796886124800,
3081 30324746107656000, 36389695329187200, 48519593772249600, 60649492215312000,
3082 72779390658374400, 74801040398884800, 106858629141264000,
3083 112201560598327200, 149602080797769600, 224403121196654400,
3084 299204161595539200, 374005201994424000, 448806242393308800,
3085 673209363589963200, 748010403988848000, 897612484786617600,
3086 1122015605983272000, 1346418727179926400, 1795224969573235200,
3087 2244031211966544000, 2692837454359852800, 3066842656354276800,
3088 4381203794791824000, 4488062423933088000, 6133685312708553600,
3089 8976124847866176000, 9200527969062830400, 12267370625417107200ULL,
3090 15334213281771384000ULL, 18401055938125660800ULL}; /* clang-format on */
3091 return highly_composites;
3092}
3093
3094// O(log(right)) approximately.
3095inline uint64_t highly_composite_upto(uint64_t right) {
3096 for (int i = static_cast<int>(highly_composites().size()) - 1; i >= 0; --i)
3097 if (highly_composites()[i] <= right)
3098 return highly_composites()[i];
3099
3100 throw detail::there_is_no_upto_error("highly composite number", right);
3101}
3102
3103// O(log^3 (right)) expected.
3104// Generates a random prime in [left, right].
3105inline uint64_t gen_prime(uint64_t left, uint64_t right) {
3106 if (right < left or right < 2)
3107 throw detail::there_is_no_in_range_error("prime", left, right);
3108 left = std::max<uint64_t>(left, 2);
3109 // Every candidate here is prime; prime_gap_upto requires right >= 4.
3110 if (right <= 3)
3111 return next(left, right);
3112 auto [l_gap, r_gap] = prime_gap_upto(right);
3113 if (right - left + 1 <= r_gap - l_gap + 1) {
3114 // There might be no primes in the range.
3115 std::vector<uint64_t> vals(right - left + 1);
3116 iota(vals.begin(), vals.end(), left);
3117 shuffle(vals.begin(), vals.end());
3118 for (uint64_t i : vals)
3119 if (is_prime(i))
3120 return i;
3121 throw detail::there_is_no_in_range_error("prime", left, right);
3122 }
3123
3124 uint64_t n;
3125 do {
3126 n = next(left, right);
3127 } while (!is_prime(n));
3128 return n;
3129}
3130
3131// O(log^3 (left)) expected.
3132// left <= 2^64 - 59.
3133inline uint64_t prime_from(uint64_t left) {
3134 tgen_ensure(left <= std::numeric_limits<uint64_t>::max() - 58,
3135 "math: invalid bound");
3136 for (uint64_t i = std::max<uint64_t>(2, left);; ++i)
3137 if (is_prime(i))
3138 return i;
3139}
3140
3141// O(log^3 (right)) expected.
3142inline uint64_t prime_upto(uint64_t right) {
3143 if (right >= 2)
3144 for (uint64_t i = right; i >= 2; --i)
3145 if (is_prime(i))
3146 return i;
3147 throw detail::there_is_no_upto_error("prime", right);
3148}
3149
3150// O(n^(1/4) log n) expected.
3151// 0 < n.
3152inline int num_divisors(uint64_t n) {
3153 int divisors = 1;
3154 for (auto [p, e] : factor_by_prime(n))
3155 divisors *= (e + 1);
3156 return divisors;
3157}
3158
3159// Random number in [left, right] with `divisor_count` divisors.
3160// O(log(right) log(divisor_count)).
3161// divisor_count must be prime.
3162inline uint64_t gen_divisor_count(uint64_t left, uint64_t right,
3163 int divisor_count) {
3164 tgen_ensure(divisor_count > 0 and is_prime(divisor_count),
3165 "math: divisor count must be prime");
3166 int root = divisor_count - 1;
3167 uint64_t lo = detail::kth_root_floor(left, root);
3168 if (*detail::expo(lo, root, left) < left)
3169 ++lo;
3170 uint64_t p = gen_prime(lo, detail::kth_root_floor(right, root));
3171 return *detail::expo(p, root, right);
3172}
3173
3174// O(|mods| + log (right)).
3175// |rems| = |mods|.
3176// rems_i < mods_i.
3177inline uint64_t gen_congruent(uint64_t left, uint64_t right,
3178 std::vector<uint64_t> rems,
3179 std::vector<uint64_t> mods) {
3180 if (left > right)
3181 throw detail::there_is_no_in_range_error("congruent number", left,
3182 right);
3183 tgen_ensure(rems.size() == mods.size(),
3184 "math: number of remainders and mods must be the same");
3185 tgen_ensure(rems.size() > 0, "math: must have at least one congruence");
3186
3187 // Shortcuts inspect every modulus, so validate them all before combining.
3188 for (size_t i = 0; i < rems.size(); ++i)
3189 tgen_ensure(rems[i] < mods[i],
3190 "math: remainder must be smaller than the mod");
3191
3192 detail::crt crt;
3193 for (int i = 0; i < static_cast<int>(rems.size()); ++i) {
3194 crt = crt * detail::crt(rems[i], mods[i]);
3195
3196 if (crt.a == -1)
3197 throw detail::there_is_no_in_range_error("congruent number", left,
3198 right);
3199 if (crt.m > right) {
3200 if (!(left <= crt.a and crt.a <= right))
3201 throw detail::there_is_no_in_range_error("congruent number",
3202 left, right);
3203
3204 for (int j = 0; j < static_cast<int>(rems.size()); ++j)
3205 if (crt.a % mods[j] != rems[j])
3206 throw detail::there_is_no_in_range_error("congruent number",
3207 left, right);
3208 return static_cast<uint64_t>(crt.a);
3209 }
3210 }
3211
3212 uint64_t k_min =
3213 crt.a >= left
3214 ? 0
3215 : static_cast<uint64_t>(((left - crt.a) + crt.m - 1) / crt.m);
3216 uint64_t k_max = static_cast<uint64_t>((right - crt.a) / crt.m);
3217
3218 if (k_min > k_max)
3219 throw detail::there_is_no_in_range_error("congruent number", left,
3220 right);
3221
3222 return static_cast<uint64_t>(crt.a + next(k_min, k_max) * crt.m);
3223}
3224
3225// O(log (right)).
3226// rem < mod.
3227inline uint64_t gen_congruent(uint64_t left, uint64_t right, uint64_t rem,
3228 uint64_t mod) {
3229 return gen_congruent(left, right, std::vector<uint64_t>({rem}),
3230 std::vector<uint64_t>({mod}));
3231}
3232
3233// First congruent number >= left.
3234// O(|mods| + log (left)).
3235// |rems| = |mods|.
3236// rems_i < mods_i.
3237inline uint64_t congruent_from(uint64_t left, std::vector<uint64_t> rems,
3238 std::vector<uint64_t> mods) {
3239 tgen_ensure(rems.size() == mods.size(),
3240 "math: number of remainders and mods must be the same");
3241 tgen_ensure(rems.size() > 0, "math: must have at least one congruence");
3242
3243 // Shortcuts inspect every modulus, so validate them all before combining.
3244 for (size_t i = 0; i < rems.size(); ++i)
3245 tgen_ensure(rems[i] < mods[i],
3246 "math: remainder must be smaller than the mod");
3247
3248 detail::crt crt;
3249 for (int i = 0; i < static_cast<int>(rems.size()); ++i) {
3250 crt = crt * detail::crt(rems[i], mods[i]);
3251
3252 if (crt.a == -1)
3253 throw detail::there_is_no_from_error("congruent number", left);
3254 if (crt.m > std::numeric_limits<uint64_t>::max()) {
3255 if (crt.a < left)
3256 throw detail::error(
3257 "math: congruent number does not exist or is too large");
3258
3259 for (int j = 0; j < static_cast<int>(rems.size()); ++j)
3260 if (crt.a % mods[j] != rems[j])
3261 throw detail::error("math: congruent number does "
3262 "not exist or is too large");
3263 return static_cast<uint64_t>(crt.a);
3264 }
3265 }
3266
3267 uint64_t k = 0;
3268 if (crt.a < left)
3269 k = static_cast<uint64_t>(((left - crt.a) + crt.m - 1) / crt.m);
3270 detail::i128 result = crt.a + k * crt.m;
3271
3272 if (result > std::numeric_limits<uint64_t>::max())
3273 throw detail::error("math: congruent number is too large");
3274 return static_cast<uint64_t>(result);
3275}
3276
3277// O(log (left))
3278// rem < mod.
3279inline uint64_t congruent_from(uint64_t left, uint64_t rem, uint64_t mod) {
3280 return congruent_from(left, std::vector<uint64_t>{rem},
3281 std::vector<uint64_t>{mod});
3282}
3283
3284// Last congruent number <= right.
3285// O(|mods| + log (right)).
3286// |rems| = |mods|.
3287// rems_i < mods_i.
3288inline uint64_t congruent_upto(uint64_t right, std::vector<uint64_t> rems,
3289 std::vector<uint64_t> mods) {
3290 tgen_ensure(rems.size() == mods.size(),
3291 "math: number of remainders and mods must be the same");
3292 tgen_ensure(rems.size() > 0, "math: must have at least one congruence");
3293
3294 // Shortcuts inspect every modulus, so validate them all before combining.
3295 for (size_t i = 0; i < rems.size(); ++i)
3296 tgen_ensure(rems[i] < mods[i],
3297 "math: remainder must be smaller than the mod");
3298
3299 detail::crt crt;
3300 for (int i = 0; i < static_cast<int>(rems.size()); ++i) {
3301
3302 crt = crt * detail::crt(rems[i], mods[i]);
3303
3304 if (crt.a == -1)
3305 throw detail::there_is_no_upto_error("congruent number", right);
3306 if (crt.m > right) {
3307 if (!(crt.a <= right))
3308 throw detail::there_is_no_upto_error("congruent number", right);
3309
3310 for (int j = 0; j < static_cast<int>(rems.size()); ++j)
3311 if (crt.a % mods[j] != rems[j])
3312 throw detail::there_is_no_upto_error("congruent number",
3313 right);
3314 return static_cast<uint64_t>(crt.a);
3315 }
3316 }
3317
3318 if (crt.a > right)
3319 throw detail::there_is_no_upto_error("congruent number", right);
3320
3321 uint64_t k = static_cast<uint64_t>((right - crt.a) / crt.m);
3322 detail::i128 result = crt.a + k * crt.m;
3323
3324 if (result < 0)
3325 throw detail::there_is_no_upto_error("congruent number", right);
3326 return static_cast<uint64_t>(result);
3327}
3328
3329// O(log r)
3330// rem < mod.
3331inline uint64_t congruent_upto(uint64_t right, uint64_t rem, uint64_t mod) {
3332 return congruent_upto(right, std::vector<uint64_t>{rem},
3333 std::vector<uint64_t>{mod});
3334}
3335
3336// Mod used for FFT/NTT.
3337inline constexpr int FFT_MOD = 998244353;
3338
3339// Fibonacci sequence up to 2^64.
3340inline const std::vector<uint64_t> &fibonacci() {
3341 static const std::vector<uint64_t> fib = [] {
3342 std::vector<uint64_t> v = {0, 1};
3343 while (v.back() <=
3344 std::numeric_limits<uint64_t>::max() - v[v.size() - 2])
3345 v.push_back(v.back() + v[v.size() - 2]);
3346 return v;
3347 }();
3348 return fib;
3349}
3350
3351// Partition is ordered (composition), that is, (1, 1, 2) != (1, 2, 1).
3352// O(n).
3353// 0 < n.
3354// 0 < part_left.
3355inline std::vector<int>
3356gen_partition(int n, int part_left = 1,
3357 std::optional<int> part_right = std::nullopt) {
3358 if (!part_right.has_value())
3359 part_right = n;
3360 part_right = std::min(*part_right, n);
3361 tgen_ensure(n > 0 and part_left > 0,
3362 "math: invalid parameters to gen_partition");
3363 // A feasible number of parts lies between ceil(n / right) and n / left.
3364 // Write the ceiling without n + right - 1 to avoid overflow.
3365 tgen_ensure(part_left <= *part_right and
3366 (n - 1) / *part_right + 1 <= n / part_left,
3367 "math: no such partition");
3368 if (part_left == *part_right)
3369 return std::vector<int>(n / part_left, part_left);
3370 if (n / part_left == 1)
3371 return {n};
3372
3373 // dp[i] = log(number of ways to add to i).
3374 // Widen before adding one to avoid overflow at INT_MAX.
3375 std::vector<long double> dp(static_cast<size_t>(n) + 1, detail::LOG_ZERO);
3376 std::vector<long double> suffix(dp.size());
3377 dp[0] = detail::LOG_ONE;
3378 int width = *part_right - part_left + 1, block_start = 0;
3379 long double prefix = detail::LOG_ZERO;
3380 for (int r = 0; r <= n - part_left; ++r) {
3381 if (r - block_start == width) {
3382 // The previous block is now complete. Its suffixes and the new
3383 // block's prefix give each window sum without cancellation.
3384 for (int j = r - 1; j > block_start; --j) {
3385 suffix[j] = dp[j];
3386 if (j + 1 < r)
3387 suffix[j] = detail::add_log_space(suffix[j], suffix[j + 1]);
3388 }
3389 block_start = r;
3390 prefix = detail::LOG_ZERO;
3391 }
3392 prefix = detail::add_log_space(prefix, dp[r]);
3393 long double window = prefix;
3394 int l = r - width + 1;
3395 if (0 < l and l < block_start)
3396 window = detail::add_log_space(window, suffix[l]);
3397 dp[r + part_left] = window;
3398 }
3399
3400 std::vector<int> part;
3401 int sum = n;
3402 while (sum > 0) {
3403 int l = std::max(0, sum - *part_right), r = sum - part_left;
3404 long double random =
3405 detail::log_space(next<long double>(0, 1)) + dp[sum];
3406 long double cumulative = detail::LOG_ZERO;
3407 int nxt_sum = -1;
3408 // Scan only as far as the chosen part; total sampling work is O(n).
3409 // Keep the last feasible choice if rounding leaves a tiny remainder.
3410 for (int j = r; j >= l; --j) {
3411 if (dp[j] == detail::LOG_ZERO)
3412 continue;
3413 nxt_sum = j;
3414 cumulative = detail::add_log_space(cumulative, dp[j]);
3415 if (random < cumulative)
3416 break;
3417 }
3418 detail::tgen_ensure_against_bug(nxt_sum >= 0,
3419 "math: no completion in gen_partition");
3420 part.push_back(sum - nxt_sum);
3421 sum = nxt_sum;
3422 }
3423
3424 return part;
3425}
3426
3427// Partition is ordered (composition), that is, (1, 1, 2) != (1, 2, 1).
3428// O(n) time/memory if part_right is not set, O(n * k) time/memory otherwise.
3429// Unbounded partitions with more than INT_MAX positions instead use
3430// O(k log k) expected time and O(k) memory to sample and sort the cuts.
3431// 0 < k <= n.
3432// 0 <= part_left.
3433inline std::vector<int>
3434gen_partition_fixed_size(int n, int k, int part_left = 0,
3435 std::optional<int> part_right = std::nullopt) {
3436 if (!part_right.has_value())
3437 part_right = n;
3438 part_right = std::min(*part_right, n);
3439 tgen_ensure(0 < k and k <= n and part_left >= 0,
3440 "math: invalid parameters to gen_partition_fixed_size");
3441 tgen_ensure(static_cast<long long>(k) * part_left <= n and
3442 n <= static_cast<long long>(k) * (*part_right),
3443 "math: no such partition");
3444
3445 // What we need to distribute to the parts.
3446 int s = n - k * part_left;
3447
3448 std::vector<int> part(k);
3449 if (*part_right == n) {
3450 // Stars and bars - O(n).
3451 std::vector<int> cuts = {-1};
3452
3453 // Stars-and-bars positions can exceed int even when every part fits.
3454 long long total_wide = static_cast<long long>(s) + k - 1;
3455 if (total_wide > std::numeric_limits<int>::max()) {
3456 // Sample the same uniform subset of delimiters without scanning
3457 // billions of positions. Keep the ordinary-range fast path below.
3458 auto wide_cuts = distinct_range<long long>(0, total_wide - 1)
3459 .gen_list(k - 1)
3460 .to_std();
3461 std::sort(wide_cuts.begin(), wide_cuts.end());
3462 wide_cuts.push_back(total_wide);
3463 long long previous = -1;
3464 for (int i = 0; i < k; ++i) {
3465 part[i] =
3466 static_cast<int>(wide_cuts[i] - previous - 1) + part_left;
3467 previous = wide_cuts[i];
3468 }
3469 return part;
3470 }
3471 int total = static_cast<int>(total_wide), bars = k - 1;
3472 for (int i = 0; i < total and bars > 0; ++i)
3473 if (next<long double>(0, 1) <
3474 static_cast<long double>(bars) / (total - i)) {
3475 cuts.push_back(i);
3476 --bars;
3477 }
3478 cuts.push_back(total);
3479
3480 // Recovers parts.
3481 for (int i = 0; i < k; ++i)
3482 part[i] = cuts[i + 1] - cuts[i] - 1;
3483 } else {
3484 // DP with log trick - O(nk).
3485 int u = *part_right - part_left;
3486 // Complementing each part preserves uniformity and reduces the sum.
3487 // Use a wide product for overflow safety before comparing capacities.
3488 long long capacity = static_cast<long long>(k) * u;
3489 bool complement = s > capacity - s;
3490 if (complement)
3491 s = static_cast<int>(capacity - s);
3492 if (s == 0)
3493 return std::vector<int>(k, complement ? *part_right : part_left);
3494
3495 // dp[i][j] = log(#ways to fill i parts with sum j).
3496 std::vector<std::vector<long double>> dp(
3497 k + 1, std::vector<long double>(s + 1, detail::LOG_ZERO));
3498 dp[0][0] = detail::LOG_ONE;
3499 std::vector<long double> suffix(s + 1);
3500
3501 for (int i = 1; i <= k; ++i) {
3502 long long row_max = static_cast<long long>(i) * u;
3503 int middle = static_cast<int>(std::min<long long>(s, row_max / 2));
3504 int suffix_max =
3505 std::min(middle / (u + 1) * (u + 1) - 1,
3506 static_cast<int>(std::min<long long>(s, row_max - u)));
3507 // Each window of u + 1 entries spans at most two blocks. Combine
3508 // a block suffix and prefix to avoid cancellation from subtraction.
3509 for (int j = suffix_max; j >= 0; --j) {
3510 suffix[j] = dp[i - 1][j];
3511 if (j < suffix_max and j % (u + 1) != u)
3512 suffix[j] = detail::add_log_space(suffix[j], suffix[j + 1]);
3513 }
3514
3515 long double prefix = detail::LOG_ZERO;
3516 for (int j = 0; j <= middle; ++j) {
3517 if (j % (u + 1) == 0)
3518 prefix = detail::LOG_ZERO;
3519 prefix = detail::add_log_space(prefix, dp[i - 1][j]);
3520 dp[i][j] = prefix;
3521 if (j > u and j % (u + 1) != u)
3522 dp[i][j] = detail::add_log_space(prefix, suffix[j - u]);
3523 }
3524 // Counts are symmetric under replacing each part x by u - x.
3525 for (int j = middle + 1; j <= std::min<long long>(s, row_max); ++j)
3526 dp[i][j] = dp[i][static_cast<int>(row_max - j)];
3527 }
3528
3529 // Recovers parts backwards.
3530 int left_to_distribute = s;
3531 for (int i = k; i >= 1; --i) {
3532 long double log_total = dp[i][left_to_distribute];
3533 int lower = static_cast<int>(std::max<long long>(
3534 0, left_to_distribute - static_cast<long long>(i - 1) * u));
3535 int upper = std::min(u, left_to_distribute);
3536 detail::tgen_ensure_against_bug(
3537 log_total != detail::LOG_ZERO,
3538 "math: total == 0 in gen_partition_fixed_size");
3539
3540 // Now we choose a number with probability proportional to
3541 // dp[i-1][.].
3542
3543 // log(rand() * total) = log(rand()) + log(total).
3544 long double random =
3545 detail::log_space(next<long double>(0, 1)) + log_total;
3546
3547 long double cur_prob = detail::LOG_ZERO;
3548 // The final feasible value also absorbs cumulative rounding error.
3549 int chosen = upper;
3550 for (int j = lower; j < upper; ++j) {
3551 cur_prob = detail::add_log_space(
3552 cur_prob, dp[i - 1][left_to_distribute - j]);
3553 if (random < cur_prob) {
3554 chosen = j;
3555 break;
3556 }
3557 }
3558
3559 part[k - i] = complement ? u - chosen : chosen;
3560 left_to_distribute -= chosen;
3561 }
3562 }
3563
3564 for (int &i : part)
3565 i += part_left;
3566 return part;
3567}
3568
3569// Partition is ordered (composition), that is, (1, 1, 2) != (1, 2, 1).
3570// Inspired by jngen rndm.partition: random delimiters, sort, gap recovery;
3571// omits jngen's part reordering, shuffles, and two-pass redistribution.
3572// 0 < k <= n.
3573// 0 <= part_left.
3574// Not uniformly random; optimized for speed.
3575// O(k log k).
3577 uint64_t n, int k, uint64_t part_left = 0,
3578 std::optional<uint64_t> part_right = std::nullopt) {
3579 if (!part_right.has_value())
3580 part_right = n;
3581 part_right = std::min(*part_right, n);
3582
3583 detail::u128 n128 = n;
3584 detail::u128 k128 = k;
3585 detail::u128 part_left128 = part_left;
3586 detail::u128 part_right128 = *part_right;
3587
3588 tgen_ensure(k > 0 and k128 <= n128,
3589 "math: invalid parameters to gen_partition_fixed_size_fast");
3590 tgen_ensure(part_right128 >= part_left128 and
3591 k128 * part_left128 <= n128 and
3592 k128 * part_right128 >= n128,
3593 "math: no such partition");
3594
3595 uint64_t slack_total = static_cast<uint64_t>(n128 - k128 * part_left128);
3596 uint64_t slack_max = static_cast<uint64_t>(part_right128 - part_left128);
3597
3598 std::vector<uint64_t> part(k);
3599 if (k == 1) {
3600 part[0] = slack_total;
3601 } else {
3602 std::vector<uint64_t> cuts(k - 1);
3603 for (uint64_t &d : cuts)
3604 d = next<uint64_t>(0, slack_total);
3605 std::sort(cuts.begin(), cuts.end());
3606
3607 uint64_t prev = 0;
3608 for (int i = 0; i + 1 < k; ++i) {
3609 part[i] = cuts[i] - prev;
3610 prev = cuts[i];
3611 }
3612 part[k - 1] = slack_total - prev;
3613 }
3614
3615 auto add_part_left = [part_left](uint64_t x) -> uint64_t {
3616 detail::u128 val = x + part_left;
3617 detail::tgen_ensure_against_bug(
3618 val <= std::numeric_limits<uint64_t>::max(),
3619 "math: part + part_left exceeds uint64_t in "
3620 "gen_partition_fixed_size_fast");
3621 return static_cast<uint64_t>(val);
3622 };
3623
3624 if (slack_max >= slack_total) {
3625 for (uint64_t &x : part)
3626 x = add_part_left(x);
3627 return part;
3628 }
3629
3630 detail::u128 remaining = 0;
3631 for (uint64_t &x : part) {
3632 if (x > slack_max) {
3633 remaining += x - slack_max;
3634 x = slack_max;
3635 }
3636 x = add_part_left(x);
3637 }
3638
3639 if (remaining > 0) {
3640 for (uint64_t &x : part) {
3641 if (x < *part_right && remaining > 0) {
3642 detail::u128 room = *part_right - x;
3643 detail::u128 add = std::min(remaining, room);
3644 detail::u128 val = x + add;
3645 detail::tgen_ensure_against_bug(
3646 val <= *part_right,
3647 "math: part exceeds part_right after redistribution in "
3648 "gen_partition_fixed_size_fast");
3649 x = static_cast<uint64_t>(val);
3650 remaining -= add;
3651 }
3652 }
3653 detail::tgen_ensure_against_bug(
3654 remaining == 0, "math: remaining mass after redistribution in "
3655 "gen_partition_fixed_size_fast");
3656 }
3657
3658 return part;
3659}
3660
3661// Random partition of elements into k ordered groups (input order preserved).
3662// If max_size is unset, part sizes are uniform via gen_partition_fixed_size.
3663// If max_size is set, uses gen_partition_fixed_size_fast (not uniform).
3664// O(n) if max_size is unset; O(n + k log k) if max_size is set.
3665template <typename T>
3666std::vector<std::vector<T>>
3667partition_elements(std::vector<T> elements, int k, int min_size = 0,
3668 std::optional<uint64_t> max_size = std::nullopt) {
3669 size_t n = elements.size();
3670 tgen_ensure(k > 0, "math: partition_elements: k must be positive");
3671 tgen_ensure(min_size >= 0,
3672 "math: partition_elements: min_size must be non-negative");
3673
3674 std::vector<uint64_t> sizes;
3675 if (max_size.has_value()) {
3676 sizes = gen_partition_fixed_size_fast(n, k, min_size, max_size);
3677 } else {
3678 for (int sz :
3679 gen_partition_fixed_size(static_cast<int>(n), k, min_size))
3680 sizes.push_back(sz);
3681 }
3682
3683 std::vector<std::vector<T>> groups;
3684 groups.reserve(k);
3685 size_t pos = 0;
3686 for (uint64_t sz : sizes) {
3687 groups.emplace_back(elements.begin() + pos,
3688 elements.begin() + pos + sz);
3689 pos += sz;
3690 }
3691 return groups;
3692}
3693
3694}; // namespace math
3695
3696/**************
3697 * *
3698 * STRING *
3699 * *
3700 **************/
3701
3702namespace detail {
3703
3704/*
3705 * Regex.
3706 *
3707 * Compatible with testlib's regex.
3708 *
3709 * Operations:
3710 * - A single character yields itself ("a", "3").
3711 * - A list of characters inside square braces yields any a random element
3712 * from the list ("[abc123]").
3713 * - A range of characters is equivalent to listing them ("[a-z1-9A-Z]").
3714 * - A pattern followed by {n} yields the pattern repeated n times ("a{3}").
3715 * - A pattern followed by {l,r} yields the pattern repeated between l and r
3716 * times, uniformly at random ("a{3,5}").
3717 * - A list of patterns separated by | yields a random pattern from the
3718 * list, uniformly at random ("abc|def|ghi").
3719 * - Parentheses can be used for grouping ("a((a|b){3})").
3720 *
3721 * Examples:
3722 * 1. str("[1-9][0-9]{1,2}") generates two- or three-digit numbers.
3723 * 2. str("a[b-d]{2}|e") generates "e" or a random string of length 3, with
3724 * the first character being 'a' and the second and
3725 * third characters being 'b', 'c', or 'd'.
3726 * 3. str("[1-9][0-9]{%d}", n-1) generates n-digit numbers.
3727 *
3728 * Operations defined by {n} and {l,r} are applied from left to right, and
3729 * the pattern that comes before has its delimiters defined either by () or
3730 * [] at its end or is taken from the beginning of the pattern (in
3731 * "a[bc]{2}", "{2}" is applied to "[bc]", and in "[01]abc{3}", the "{3}" is
3732 * applied to "[01]abc").
3733 */
3734
3735// If it has children, it is either a SEQ or an OR group, defined by the
3736// pattern_ field.
3737struct regex_node {
3738 // Considered to be repetition of left_bound != -1, pattern if
3739 // children_.empty(), otherwise "SEQ" or "OR", defined by the pattern_
3740 // field.
3741 std::string
3742 pattern_; // Either pattern, or "SEQ" or "OR" (if !children_.empty()).
3743 std::vector<regex_node> children_; // Children, when SEQ or OR.
3744 int left_bound_, right_bound_; // Left and right bounds of the repetition,
3745 // or -1 if not a repetition.
3746 double
3747 log_space_num_ways_; // Log space number of ways to match the pattern.
3748 std::optional<distinct_container<char>>
3749 distinct_; // Distinct generator for the pattern, for [chars].
3750
3751 // c or [chars].
3752 regex_node(const std::string &pattern)
3753 : pattern_(pattern), left_bound_(-1), right_bound_(-1) {
3754 if (pattern.size() == 1) {
3755 log_space_num_ways_ = math::detail::LOG_ONE;
3756 return;
3757 }
3758 tgen_ensure_against_bug(pattern[0] == '[' and pattern.back() == ']',
3759 "str: invalid regex: expected character class");
3760 int size = static_cast<int>(pattern.size()) - 2;
3761 log_space_num_ways_ =
3762 static_cast<double>(math::detail::log_space(size));
3763 distinct_ = distinct_container<char>(pattern.substr(1, size));
3764 }
3765 // SEQ or OR.
3766 regex_node(const std::string &pattern, std::vector<regex_node> &children)
3767 : pattern_(pattern), left_bound_(-1), right_bound_(-1) {
3768 if (pattern == "SEQ") {
3769 // Multiply the number of ways.
3770 log_space_num_ways_ = math::detail::LOG_ONE;
3771 for (const auto &child : children)
3772 log_space_num_ways_ += child.log_space_num_ways_;
3773 } else if (pattern == "OR") {
3774 // Add the number of ways.
3775 log_space_num_ways_ = math::detail::LOG_ZERO;
3776 for (const auto &child : children)
3777 log_space_num_ways_ =
3778 static_cast<double>(math::detail::add_log_space(
3779 log_space_num_ways_, child.log_space_num_ways_));
3780 } else
3781 tgen_ensure_against_bug("str: invalid regex: expected SEQ or OR");
3782
3783 children_ = std::move(children);
3784 children.clear();
3785 }
3786 // REP.
3787 regex_node(int left_bound, int right_bound, regex_node &child)
3788 : pattern_("REP"), left_bound_(left_bound), right_bound_(right_bound) {
3789 log_space_num_ways_ = math::detail::LOG_ZERO;
3790 for (int i = left_bound; i <= right_bound; ++i)
3791 log_space_num_ways_ =
3792 static_cast<double>(math::detail::add_log_space(
3793 log_space_num_ways_, i * child.log_space_num_ways_));
3794
3795 children_.push_back(std::move(child));
3796 }
3797};
3798
3799// State of the regex parser.
3800struct regex_state {
3801 std::vector<regex_node> cur; // Current sequence of nodes.
3802 std::vector<regex_node> branches; // Branches of the current OR group.
3803};
3804
3805// Creates a SEQ node from the current state.
3806inline regex_node make_regex_seq(regex_state &st) {
3807 return regex_node("SEQ", st.cur);
3808}
3809
3810// Finishes current state.
3811inline regex_node finish_regex_state(regex_state &st) {
3812 // SEQ.
3813 if (st.branches.empty())
3814 return make_regex_seq(st);
3815
3816 // OR.
3817 st.branches.push_back(make_regex_seq(st));
3818 return regex_node("OR", st.branches);
3819}
3820
3821// Parses a regex pattern into a tree, computing the number of ways to match the
3822// pattern.
3823inline regex_node parse_regex(std::string regex) {
3824 std::string new_regex;
3825 for (char c : regex)
3826 if (c != ' ')
3827 new_regex += c;
3828 swap(regex, new_regex);
3829 regex_state cur;
3830 std::vector<regex_state> stack;
3831
3832 for (size_t i = 0; i < regex.size(); ++i) {
3833 char c = regex[i];
3834
3835 if (c == '(') {
3836 // Pushes the current state to the stack.
3837 stack.push_back(std::move(cur));
3838 cur = regex_state();
3839 } else if (c == ')') {
3840 // Finishes the current state, and adds it to the parent.
3841 regex_node node = finish_regex_state(cur);
3842
3843 tgen_ensure(!stack.empty(), "str: invalid regex: unmatched `)`");
3844 cur = std::move(stack.back());
3845 stack.pop_back();
3846
3847 cur.cur.push_back(std::move(node));
3848 } else if (c == '|') {
3849 // Starts a new OR group.
3850 regex_node node = make_regex_seq(cur);
3851 cur.branches.push_back(std::move(node));
3852 } else if (c == '[') {
3853 // Parses a character class.
3854 std::string chars;
3855
3856 for (++i; i < regex.size() and regex[i] != ']'; ++i) {
3857 if (i + 2 < regex.size() and regex[i + 1] == '-') {
3858 char a = regex[i], b = regex[i + 2];
3859 if (a > b)
3860 std::swap(a, b);
3861 // Widen the counter so incrementing CHAR_MAX cannot wrap.
3862 for (int x = a; x <= b; ++x)
3863 chars += static_cast<char>(x);
3864 i += 2;
3865 } else
3866 chars += regex[i];
3867 }
3868
3869 tgen_ensure(i < regex.size() and regex[i] == ']',
3870 "str: invalid regex: unmatched `[`");
3871 cur.cur.emplace_back("[" + chars + "]");
3872 } else if (c == '{') {
3873 // Parses a repetition.
3874 ++i;
3875 int l = -1, r = -1;
3876
3877 while (i < regex.size() and
3878 isdigit(static_cast<unsigned char>(regex[i]))) {
3879 if (l == -1)
3880 l = 0;
3881 tgen_ensure(l <= static_cast<int>(1e8),
3882 "str: invalid regex: number too large inside `{}`");
3883 l = 10 * l + (regex[i] - '0');
3884 ++i;
3885 }
3886
3887 if (i < regex.size() and regex[i] == ',') {
3888 ++i;
3889 while (i < regex.size() and
3890 isdigit(static_cast<unsigned char>(regex[i]))) {
3891 if (r == -1)
3892 r = 0;
3894 r <= static_cast<int>(1e8),
3895 "str: invalid regex: number too large inside `{}`");
3896 r = 10 * r + (regex[i] - '0');
3897 ++i;
3898 }
3899 } else
3900 r = l;
3901
3902 tgen_ensure(i < regex.size() and regex[i] == '}',
3903 "str: invalid regex: unmatched `{`");
3904 tgen_ensure(l != -1 and r != -1,
3905 "str: invalid regex: missing number inside `{}`");
3906 tgen_ensure(l <= r,
3907 "str: invalid regex: invalid range inside `{}`");
3908
3909 // Creates a REP node from the previous node.
3910 tgen_ensure(!cur.cur.empty(),
3911 "str: invalid regex: expected expression before `{}`");
3912
3913 regex_node rep(l, r, cur.cur.back());
3914 cur.cur.pop_back();
3915 cur.cur.push_back(std::move(rep));
3916 } else {
3917 // Creates a char node.
3918 cur.cur.emplace_back(std::string(1, c));
3919 }
3920 }
3921
3922 tgen_ensure(stack.empty(), "str: invalid regex: unmatched `(`");
3923 return finish_regex_state(cur);
3924}
3925
3926// Generates a uniformly random string that matches the given regex.
3927inline void gen_regex(const regex_node &node, std::string &str) {
3928 // For [chars], generate a random character from the list.
3929 if (node.pattern_[0] == '[') {
3930 str += node.pattern_[1 + next<int>(
3931 0, static_cast<int>(node.pattern_.size()) -
3932 3)];
3933 return;
3934 }
3935
3936 // For REP, generate a random number of times to repeat the pattern.
3937 if (node.left_bound_ != -1) {
3938 // Generates a random value W from 0 to num_ways.
3939 // log(W) = log(random(0, 1) * num_ways)
3940 // = log(random(0, 1)) + log(num_ways).
3941 double log_rand =
3942 static_cast<double>(math::detail::log_space(next<double>(0, 1))) +
3943 node.log_space_num_ways_;
3944 double cur_prob = math::detail::LOG_ZERO;
3945 double child_num_ways = node.children_[0].log_space_num_ways_;
3946
3947 for (int i = node.left_bound_; i <= node.right_bound_; ++i) {
3948 cur_prob = static_cast<double>(
3949 math::detail::add_log_space(cur_prob, i * child_num_ways));
3950 if (log_rand <= cur_prob) {
3951 for (int j = 0; j < i; ++j)
3952 gen_regex(node.children_[0], str);
3953 return;
3954 }
3955 }
3956
3957 tgen_ensure_against_bug(false,
3958 "str: log_rand > cur_prob in REP gen_regex");
3959 }
3960
3961 // For SEQ, generate all children.
3962 if (node.pattern_ == "SEQ") {
3963 for (const regex_node &child : node.children_)
3964 gen_regex(child, str);
3965 return;
3966 }
3967
3968 // For OR, generate a random child.
3969 if (!node.children_.empty() and node.pattern_ == "OR") {
3970 // Generates a random value W from 0 to num_ways.
3971 // log(W) = log(random(0, 1) * num_ways)
3972 // = log(random(0, 1)) + log(num_ways).
3973 double log_rand =
3974 static_cast<double>(math::detail::log_space(next<double>(0, 1))) +
3975 node.log_space_num_ways_;
3976 double cur_prob = math::detail::LOG_ZERO;
3977
3978 for (const regex_node &child : node.children_) {
3979 cur_prob = static_cast<double>(math::detail::add_log_space(
3980 cur_prob, child.log_space_num_ways_));
3981 if (log_rand <= cur_prob) {
3982 gen_regex(child, str);
3983 return;
3984 }
3985 }
3986
3987 tgen_ensure_against_bug(false,
3988 "str: log_rand > cur_prob in OR gen_regex");
3989 }
3990
3991 // For char, generate the character.
3992 detail::tgen_ensure_against_bug(
3993 node.pattern_.size() == 1,
3994 "str: invalid regex: expected single character, but got `" +
3995 node.pattern_ + "`");
3996 str += node.pattern_[0];
3997}
3998
3999// Formats a regex string with given arguments.
4000template <typename... Args>
4001std::string regex_format(const std::string &s, Args &&...args) {
4002 if constexpr (sizeof...(Args) == 0) {
4003 return s;
4004 } else {
4005 int size = std::snprintf(nullptr, 0, s.c_str(), args...) + 1;
4006 std::string buf(size, '\0');
4007 std::snprintf(buf.data(), size, s.c_str(), args...);
4008 buf.pop_back(); // remove '\0'
4009 return buf;
4010 }
4011}
4012
4013} // namespace detail
4014
4015/*
4016 * String generator.
4017 */
4018
4019struct str : gen_base<str> {
4020 std::optional<list<char>> list_; // List of characters.
4021 std::optional<detail::regex_node>
4022 root_; // Root node of the regex tree for the whole string.
4023
4024 // Creates generator for strings of size 'size', with random characters in
4025 // [value_left, value_right].
4026 str(int size, char value_left = 'a', char value_right = 'z') {
4027 tgen_ensure(size > 0, "str: size must be positive");
4028 list_ = list<char>(size, value_left, value_right);
4029 }
4030
4031 // Creates generator for strings of size 'size', with random characters in
4032 // 'chars'.
4033 str(int size, std::set<char> chars) {
4034 tgen_ensure(size > 0, "str: size must be positive");
4035 list_ = list<char>(size, chars);
4036 }
4037
4038 // Creates generator for strings that match the given regex.
4039 template <typename... Args> str(const std::string &regex, Args &&...args) {
4040 tgen_ensure(regex.size() > 0, "str: regex must be non-empty");
4041
4042 root_ = detail::parse_regex(
4043 detail::regex_format(regex, std::forward<Args>(args)...));
4044 }
4045
4046 // Restricts strings for str[idx] = value.
4047 str &fix(int idx, char character) {
4048 tgen_ensure(!root_, "str: cannot add restriction for regex");
4049 list_->fix(idx, character);
4050 return *this;
4051 }
4052
4053 // Restricts strings for list[S] to be equal, for given subset S of indices.
4054 str &equal(std::set<int> indices) {
4055 tgen_ensure(!root_, "str: cannot add restriction for regex");
4056 list_->equal(indices);
4057 return *this;
4058 }
4059
4060 // Restricts strings for str[idx_1] = str[idx_2].
4061 str &equal(int idx_1, int idx_2) {
4062 tgen_ensure(!root_, "str: cannot add restriction for regex");
4063 list_->equal(idx_1, idx_2);
4064 return *this;
4065 }
4066
4067 // Restricts strings for str[left..right] to have all equal values.
4068 str &equal_range(int left, int right) {
4069 tgen_ensure(!root_, "str: cannot add restriction for regex");
4070 list_->equal_range(left, right);
4071 return *this;
4072 }
4073
4074 // Restricts strings for all equal chars.
4076 tgen_ensure(!root_, "str: cannot add restriction for regex");
4077 list_->all_equal();
4078 return *this;
4079 }
4080
4081 // Restricts strings for str[left..right] to be a palindrome.
4082 str &palindrome(int left, int right) {
4083 tgen_ensure(!root_, "str: cannot add restriction for regex");
4084 tgen_ensure(0 <= left and left <= right and right < list_->size_,
4085 "str: range indices must be valid");
4086 for (int i = left; i < right - (i - left); ++i)
4087 equal(i, right - (i - left));
4088 return *this;
4089 }
4090
4091 // Restricts strings for the entire string to be a palindrome.
4093 tgen_ensure(!root_, "str: cannot add restriction for regex");
4094 return palindrome(0, list_->size_ - 1);
4095 }
4096
4097 // Restricts strings for str[S] to be different (distinct), for given subset
4098 // S of indices.
4099 str &different(std::set<int> indices) {
4100 tgen_ensure(!root_, "str: cannot add restriction for regex");
4101 list_->different(indices);
4102 return *this;
4103 }
4104
4105 // Restricts strings for str[idx_1] != str[idx_2].
4106 str &different(int idx_1, int idx_2) {
4107 tgen_ensure(!root_, "str: cannot add restriction for regex");
4108 list_->different(idx_1, idx_2);
4109 return *this;
4110 }
4111
4112 // Restricts lists for list[left..right] to have all different chars.
4113 str &different_range(int left, int right) {
4114 tgen_ensure(!root_, "str: cannot add restriction for regex");
4115 list_->different_range(left, right);
4116 return *this;
4117 }
4118
4119 // Restricts strings for all chars to be different.
4121 tgen_ensure(!root_, "str: cannot add restriction for regex");
4122 list_->all_different();
4123 return *this;
4124 }
4125
4126 // Restricts adjacent characters to be different: str[i] != str[i+1].
4128 tgen_ensure(!root_, "str: cannot add restriction for regex");
4129 list_->adjacent_different();
4130 return *this;
4131 }
4132
4133 // str value.
4135 using tgen_is_sequential_tag = detail::is_sequential_tag;
4136
4137 using value_type = char;
4138 using std_type = std::string;
4139 std::string str_;
4140
4141 value(const std::string &str) : str_(str) {}
4142
4143 // Fetches size.
4144 int size() const { return static_cast<int>(str_.size()); }
4145
4146 // Fetches position idx.
4147 char &operator[](int idx) {
4148 tgen_ensure(0 <= idx and idx < size(),
4149 "str: value: index out of bounds");
4150 return str_[idx];
4151 }
4152 const char &operator[](int idx) const {
4153 tgen_ensure(0 <= idx and idx < size(),
4154 "str: value: index out of bounds");
4155 return str_[idx];
4156 }
4157
4158 // Sorts characters in non-decreasing order.
4159 // O(n log n).
4161 std::sort(str_.begin(), str_.end());
4162 return *this;
4163 }
4164
4165 // Reverses string.
4166 // O(n).
4168 std::reverse(str_.begin(), str_.end());
4169 return *this;
4170 }
4171
4172 // Lowercases all characters.
4173 // O(n).
4175 for (char &c : str_)
4176 c = static_cast<char>(
4177 std::tolower(static_cast<unsigned char>(c)));
4178 return *this;
4179 }
4180
4181 // Uppercases all characters.
4182 // O(n).
4184 for (char &c : str_)
4185 c = static_cast<char>(
4186 std::toupper(static_cast<unsigned char>(c)));
4187 return *this;
4188 }
4189
4190 // Concatenates two values.
4191 // Linear.
4192 value operator+(const value &rhs) const {
4193 return value(str_ + rhs.str_);
4194 }
4195
4196 // Shuffles string uniformly.
4197 // O(n).
4199 tgen::shuffle(str_.begin(), str_.end());
4200 return *this;
4201 }
4202
4203 // Returns a random character uniformly.
4204 // O(1).
4205 char pick() const { return str_[next<int>(0, size() - 1)]; }
4206
4207 // Returns str_[i] with probability proportional to distribution[i].
4208 // O(1).
4209 template <typename Dist>
4210 char pick_by_distribution(const std::vector<Dist> &distribution) const {
4211 tgen_ensure(static_cast<size_t>(size()) == distribution.size(),
4212 "value and distribution must have the same size");
4213 return str_[next_by_distribution(distribution)];
4214 }
4215 template <typename Dist>
4216 char pick_by_distribution(
4217 const std::initializer_list<Dist> &distribution) const {
4218 return pick_by_distribution(std::vector<Dist>(distribution));
4219 }
4220
4221 // Chooses k characters uniformly, as in a subsequence of size k.
4222 // O(n).
4223 value choose(int k) const {
4224 tgen_ensure(0 < k and k <= size(),
4225 "number of elements to choose must be valid");
4226 std::string new_str;
4227 int need = k;
4228 for (int i = 0; need > 0; ++i) {
4229 int left = size() - i;
4230 if (next(1, left) <= need) {
4231 new_str.push_back(str_[i]);
4232 need--;
4233 }
4234 }
4235 return value(new_str);
4236 }
4237
4238 // Prints to std::ostream.
4239 friend std::ostream &operator<<(std::ostream &out, const value &val) {
4240 return out << val.str_;
4241 }
4242
4243 // Gets a std::string representing the value.
4244 std::string to_std() const { return std_type(str_); }
4245 };
4246
4247 // Generates str value.
4248 // If created from restrictions: O(n log n).
4249 // If created from regex: expected linear.
4250 value gen() const {
4251 if (root_) {
4252 // Regex.
4253 std::string ret_str;
4254 gen_regex(*root_, ret_str);
4255 return value(ret_str);
4256 } else {
4257 // List.
4258 std::vector<char> vec = list_->gen().to_std();
4259 return value(std::string(vec.begin(), vec.end()));
4260 }
4261 }
4262};
4263
4264/************
4265 * *
4266 * PAIR *
4267 * *
4268 ************/
4269
4270namespace detail {
4271
4272// Generates pair first == second.
4273// O(1).
4274template <typename T> std::pair<T, T> gen_eq(T L1, T R1, T L2, T R2) {
4275 T L = std::max(L1, L2);
4276 T R = std::min(R1, R2);
4277
4278 tgen_ensure(L <= R, "pair: no valid values to generate");
4279 T x = next<T>(L, R);
4280 return {x, x};
4281}
4282
4283// Returns {R1-L1+1, R2-L2+1}.
4284template <typename T>
4285std::pair<u128, u128> get_n_and_m(T L1, T R1, T L2, T R2) {
4286 u128 n = static_cast<i128>(R1) - L1 + 1;
4287 u128 m = static_cast<i128>(R2) - L2 + 1;
4288 return {n, m};
4289}
4290
4291// Returns first + first+1 + ... + last,
4292// num_terms terms. Avoids overflow.
4293static u128 pos_arith_sum(u128 first, u128 last, u128 num_terms) {
4294 u128 x = first + last, y = num_terms;
4295
4296 // x * y / 2, avoiding overflow.
4297 if (x % 2 == 0)
4298 x /= 2;
4299 else
4300 y /= 2;
4301
4302 return x * y;
4303}
4304
4305// Generates pair first != second.
4306// O(1) expected.
4307template <typename T> std::pair<T, T> gen_neq(T L1, T R1, T L2, T R2) {
4308 auto [n, m] = get_n_and_m(L1, R1, L2, R2);
4309
4310 T L_intersect = std::max(L1, L2);
4311 T R_intersect = std::min(R1, R2);
4312 u128 inter = static_cast<i128>(R_intersect) - L_intersect + 1;
4313
4314 u128 total = n * m - inter;
4315 tgen_ensure(total > 0, "pair: no valid values to generate");
4316
4317 // Runs O(1) expected times in the worst case.
4318 T a, b;
4319 do {
4320 a = next<T>(L1, R1);
4321 b = next<T>(L2, R2);
4322 } while (a == b);
4323
4324 return {a, b};
4325}
4326
4327// For lt, splits 'second' into two regions:
4328// 1) second <= R1 -> number of 'first' is (second - L1)
4329// 2) second > R1 -> number of 'first' is (R1 - L1 + 1)
4330// Returns {count_region1, count_region2}.
4331// O(1).
4332template <typename T>
4333std::pair<u128, u128> count_lt_regions(T L1, T R1, T L2, T R2) {
4334 auto [n, m] = get_n_and_m(L1, R1, L2, R2);
4335
4336 // 'second' must be >= L1 + 1.
4337 i128 L_second = std::max<i128>(L2, static_cast<i128>(L1) + 1);
4338 i128 R_second = R2;
4339
4340 // Split point for 'second'.
4341 i128 split = std::min<i128>(R_second, R1);
4342
4343 // Region 1: b in [L_second, split].
4344 u128 len1 = std::max<i128>(0, split - L_second + 1);
4345
4346 u128 count_region1 = 0;
4347 if (len1 > 0) {
4348 // For b in [L_second, split], there are (b - L1) ways.
4349 i128 first = L_second - L1;
4350 i128 last = split - L1;
4351
4352 // Arithmetic series first + (first + 1) + ... + last, len1 terms.
4353 count_region1 = pos_arith_sum(first, last, len1);
4354 }
4355
4356 // Region 2: b > R1.
4357 // For b in [R1+1, R_second], there are 'n' ways.
4358 i128 L_second_region2 = std::max(L_second, static_cast<i128>(R1) + 1);
4359
4360 u128 len2 = std::max<i128>(0, R_second - L_second_region2 + 1);
4361 u128 count_region2 = len2 * n;
4362
4363 return {count_region1, count_region2};
4364}
4365
4366// Generates pair first < second.
4367// O(log(R1 - L1 + 1) + log(R2 - L2 + 1)).
4368template <typename T> std::pair<T, T> gen_lt(T L1, T R1, T L2, T R2) {
4369 auto [n, m] = get_n_and_m(L1, R1, L2, R2);
4370
4371 // 'second' needs to be at least L1 + 1 to have a valid value for
4372 // 'first'.
4373 i128 L_second = std::max<i128>(L2, static_cast<i128>(L1) + 1);
4374 i128 R_second = R2;
4375
4376 // Splits 'second' into two regions:
4377 // 1) b <= R1 -> number of 'first' is (b - L1);
4378 // 2) b > R1 -> number of 'first' is (R1 - L1 + 1).
4379 i128 split = std::min<i128>(R_second, R1);
4380
4381 auto [count_region1, count_region2] = count_lt_regions(L1, R1, L2, R2);
4382 u128 total = count_region1 + count_region2;
4383 tgen_ensure(total > 0, "pair: no valid values to generate");
4384
4385 u128 k = detail::next128(total);
4386 if (k < count_region1) {
4387 // Region 1: invert arithmetic series.
4388
4389 // For b in [L_second, split].
4390 u128 len1 = std::max<i128>(0, split - L_second + 1);
4391
4392 // We consider b in [L_second, L_second + d].
4393 // Each b contributes (b - L1) = base + (b - L_second).
4394 // So we sum: base + (base+1) + ... + (base+d)
4395 // d in [0, len1).
4396
4397 i128 base = L_second - L1;
4398 i128 lo = 0, hi = static_cast<i128>(len1) - 1;
4399
4400 while (lo < hi) {
4401 i128 mid = lo + (hi - lo) / 2;
4402
4403 if (pos_arith_sum(base, base + mid, mid + 1) <= k)
4404 lo = mid + 1;
4405 else
4406 hi = mid;
4407 }
4408 i128 d = lo;
4409
4410 // Subtracts prefix sum with d-1 terms from k.
4411 if (d > 0)
4412 k -= pos_arith_sum(base, base + d - 1, d);
4413
4414 // Reconstruct in i128 before narrowing: k may exceed signed T.
4415 return {static_cast<T>(i128(L1) + i128(k)),
4416 static_cast<T>(L_second + d)};
4417 } else {
4418 // Region 2: uniform block of size n.
4419 k -= count_region1;
4420
4421 // For b in [R1+1, R_second], there are 'n' ways.
4422 i128 L_second_region2 = std::max(L_second, static_cast<i128>(R1) + 1);
4423
4424 // Each offset may exceed signed T while the final coordinate fits.
4425 return {static_cast<T>(i128(L1) + i128(k % n)),
4426 static_cast<T>(L_second_region2 + i128(k / n))};
4427 }
4428}
4429
4430// Generates pair first > second.
4431// O(log(R1 - L1 + 1) + log(R2 - L2 + 1)).
4432template <typename T> std::pair<T, T> gen_gt(T L1, T R1, T L2, T R2) {
4433 auto [first, second] = gen_lt(L2, R2, L1, R1);
4434 return {second, first};
4435}
4436
4437// Generates pair first <= second.
4438// O(log(R1 - L1 + 1) + log(R2 - L2 + 1)).
4439template <typename T> std::pair<T, T> gen_leq(T L1, T R1, T L2, T R2) {
4440 // Counts how many pairs are there with first = second.
4441 i128 L_intersect = std::max(L1, L2);
4442 i128 R_intersect = std::min(R1, R2);
4443 u128 eq_count = std::max<i128>(0, R_intersect - L_intersect + 1);
4444
4445 // Counts how many pairs are there with first < second.
4446 auto [lt_region1, lt_region2] = count_lt_regions(L1, R1, L2, R2);
4447 u128 lt_count = lt_region1 + lt_region2;
4448
4449 u128 total = eq_count + lt_count;
4450 tgen_ensure(total > 0, "pair: no valid values to generate");
4451
4452 if (detail::next128(total) < eq_count)
4453 return gen_eq(L1, R1, L2, R2);
4454 return gen_lt(L1, R1, L2, R2);
4455}
4456
4457// Generates pair first >= second.
4458// O(log(R1 - L1 + 1) + log(R2 - L2 + 1)).
4459template <typename T> std::pair<T, T> gen_geq(T L1, T R1, T L2, T R2) {
4460 auto [first, second] = gen_leq(L2, R2, L1, R1);
4461 return {second, first};
4462}
4463
4464}; // namespace detail
4465
4466/*
4467 * Pair generator.
4468 *
4469 * Pairs of integral types.
4470 */
4471
4472template <typename T> struct pair : gen_base<pair<T>> {
4473 std::pair<T, T> first_, second_; // Range of first and second values.
4474 // Type of restriction.
4475 enum class restriction_type { eq, neq, lt, gt, leq, geq, unspecified };
4476 restriction_type type_ = restriction_type::unspecified;
4477
4478 // Creates a pair with random values in [first_l, first_r] and [second_l,
4479 // second_r].
4480 pair(T first_left, T first_right, T second_left, T second_right)
4481 : first_(first_left, first_right), second_(second_left, second_right) {
4482 tgen_ensure(first_left <= first_right,
4483 "pair: first range must be valid");
4484 tgen_ensure(second_left <= second_right,
4485 "pair: second range must be valid");
4486 }
4487
4488 // Creates a pair with random values in [both_l, both_r].
4489 pair(T both_left, T both_right)
4490 : pair(both_left, both_right, both_left, both_right) {}
4491
4492 // Restricts pair for first = second.
4494 type_ = restriction_type::eq;
4495 return *this;
4496 }
4497
4498 // Restricts pair for first != second.
4500 type_ = restriction_type::neq;
4501 return *this;
4502 }
4503
4504 // Restricts pair for first < second.
4506 type_ = restriction_type::lt;
4507 return *this;
4508 }
4509
4510 // Restricts pair for first > second.
4512 type_ = restriction_type::gt;
4513 return *this;
4514 }
4515
4516 // Restricts pair for first <= second.
4518 type_ = restriction_type::leq;
4519 return *this;
4520 }
4521
4522 // Restricts pair for first >= second.
4524 type_ = restriction_type::geq;
4525 return *this;
4526 }
4527
4528 // Pair value.
4530 using value_type = T;
4531 using std_type = std::pair<T, T>;
4532
4533 std::pair<T, T> pair_;
4534 char sep_;
4535
4536 value(const std::pair<T, T> &pair) : pair_(pair), sep_(' ') {}
4537 value(const T &first, const T &second)
4538 : pair_(first, second), sep_(' ') {}
4539
4540 T first() const { return pair_.first; }
4541 T second() const { return pair_.second; }
4542
4543 // Sets the separator for the pair, for printing.
4544 value &separator(char sep) {
4545 sep_ = sep;
4546 return *this;
4547 }
4548
4549 // Prints to std::ostream, separated by sep_.
4550 friend std::ostream &operator<<(std::ostream &out, const value &val) {
4551 return out << val.pair_.first << val.sep_ << val.pair_.second;
4552 }
4553
4554 // Gets a std::pair representing the value.
4555 auto to_std() const {
4556 if constexpr (!detail::is_generator_value<T>::value) {
4557 return pair_;
4558 } else {
4559 std::pair<typename T::std_type, typename T::std_type> pair(
4560 pair_.first.to_std(), pair_.second.to_std());
4561 return pair;
4562 }
4563 }
4564 };
4565
4566 // Generates a random pair.
4567 // O(log(R1 - L1 + 1) + log(R2 - L2 + 1)).
4568 value gen() const {
4569 T L1 = first_.first, R1 = first_.second;
4570 T L2 = second_.first, R2 = second_.second;
4571
4572 switch (type_) {
4573 case restriction_type::unspecified:
4574 return {next<T>(L1, R1), next<T>(L2, R2)};
4575 case restriction_type::eq:
4576 return detail::gen_eq<T>(L1, R1, L2, R2);
4577 case restriction_type::neq:
4578 return detail::gen_neq<T>(L1, R1, L2, R2);
4579 case restriction_type::lt:
4580 return detail::gen_lt<T>(L1, R1, L2, R2);
4581 case restriction_type::gt:
4582 return detail::gen_gt<T>(L1, R1, L2, R2);
4583 case restriction_type::leq:
4584 return detail::gen_leq<T>(L1, R1, L2, R2);
4585 case restriction_type::geq:
4586 return detail::gen_geq<T>(L1, R1, L2, R2);
4587 }
4588 throw detail::error("pair: unknown restriction type");
4589 }
4590};
4591
4592/************
4593 * *
4594 * TREE *
4595 * *
4596 ************/
4597
4598namespace detail {
4599
4600// Generates edges from Prufer sequence.
4601// O(n).
4602inline std::vector<std::pair<int, int>> edges_from_prufer(std::vector<int> p) {
4603 int n = static_cast<int>(p.size()) + 2;
4604
4605 // Degrees.
4606 std::vector<int> d(n, 1);
4607 for (int i : p)
4608 d[i]++;
4609
4610 // Adds last vertex.
4611 p.push_back(n - 1);
4612
4613 // Finds first vertex with degree 1.
4614 int idx, u;
4615 idx = u = static_cast<int>(find(d.begin(), d.end(), 1) - d.begin());
4616
4617 // Generates edges.
4618 std::vector<std::pair<int, int>> edges;
4619 for (int v : p) {
4620 edges.emplace_back(u, v);
4621 if (--d[v] == 1 and v < idx)
4622 u = v;
4623 else
4624 idx = u = static_cast<int>(find(d.begin() + idx + 1, d.end(), 1) -
4625 d.begin());
4626 }
4627 return edges;
4628}
4629
4630// Disjoint set union (union-find) for connectivity queries.
4631struct dsu {
4632 std::vector<int> parent_;
4633 std::vector<unsigned char> rank_;
4634
4635 // Creates a dsu with `n` elements, indexed from 0 to n-1.
4636 // Initially every element is in its own set.
4637 // O(n).
4638 dsu(int n) : parent_(n), rank_(n, 0) {
4639 for (int i = 0; i < n; ++i)
4640 parent_[i] = i;
4641 }
4642
4643 // Adds new elements to the dsu, each in their own new set.
4644 // O(k) amortized.
4645 void add_elements(int k) {
4646 for (int i = 0; i < k; ++i) {
4647 int new_id = static_cast<int>(parent_.size());
4648 parent_.push_back(new_id);
4649 rank_.push_back(0);
4650 }
4651 }
4652
4653 // Finds representative of set containing i.
4654 // O(alpha(n)) amortized, O(log n) worst case.
4655 int find(int i) {
4656 return parent_[i] == i ? i : parent_[i] = find(parent_[i]);
4657 }
4658
4659 // Merges components of `a` and `b`. Returns if the sets were united, and
4660 // false if a and b were in the same set.
4661 // O(alpha(n)) amortized, O(log n) worst case.
4662 bool unite(int a, int b) {
4663 a = find(a);
4664 b = find(b);
4665 if (a == b)
4666 return false;
4667 if (rank_[a] > rank_[b])
4668 std::swap(a, b);
4669 parent_[a] = b;
4670 if (rank_[a] == rank_[b])
4671 ++rank_[b];
4672 return true;
4673 }
4674};
4675
4676} // namespace detail
4677
4678// Forward declaration of wgraph.
4679template <typename VWeight, typename EWeight> struct wgraph;
4680
4681/*
4682 * Tree generator.
4683 *
4684 * Unrooted trees with `n` vertices, indexed from 0 to n-1.
4685 * These are unrooted undirected labeled trees, that is, isomorphism is not
4686 * taken into account. VWeight is the type of vertex weights, and EWeight is
4687 * the type of edge weights. Generator does not generate weights. The weights
4688 * are to be set in the wtree::value.
4689 */
4690
4691template <typename VWeight, typename EWeight>
4692struct wtree : gen_base<wtree<VWeight, EWeight>> {
4693 int n_; // Number of vertices.
4694 std::set<std::pair<int, int>> edges_; // Edges that were set.
4695
4696 // Creates tree generator with `n` vertices.
4697 // O(1).
4698 wtree(int n) : n_(n) {
4699 tgen_ensure(n > 0, "wtree: number of vertices must be positive");
4700 }
4701
4702 // Adds edge between u and v (this edge must be generated).
4703 // O(log n).
4704 wtree &add_edge(int u, int v) {
4705 tgen_ensure(0 <= std::min(u, v) and std::max(u, v) < n_,
4706 "wtree: vertices must be indexed in [0, n)");
4707 tgen_ensure(u != v, "wtree: cannot add self loop to tree");
4708
4709 if (u > v)
4710 std::swap(u, v);
4711 edges_.emplace(u, v);
4712 return *this;
4713 }
4714
4715 // Tree value.
4716 //
4717 // Edges are stored in both directions in adjacency list, but only u < v in
4718 // edge list.
4720 using std_type = std::pair<int, std::vector<std::set<int>>>;
4721
4722 int n_; // Number of vertices.
4723 std::vector<std::set<int>> adj_; // Adjacency list.
4724 std::vector<std::pair<int, int>> edges_; // Edge list.
4725 bool print_1_based_; // If should print vertex ids 1-based (print only).
4726 bool print_n_; // If should print n.
4727 std::optional<int> print_parents_; // If should print in parent style
4728 // (stores the root).
4729 std::optional<std::vector<VWeight>> vertex_weights_; // Vertex weights.
4730 std::optional<std::vector<EWeight>>
4731 edge_weights_; // Edge weights (in same order as edges_).
4732 detail::dsu dsu_; // Connectivity of current edges (for cycle checks).
4733
4734 // Creates value from adjacency list.
4735 // O(n).
4736 value(const std::vector<std::set<int>> &adj)
4737 : n_(static_cast<int>(adj.size())), adj_(adj),
4738 print_1_based_(false), print_n_(false), dsu_(n_) {
4739 for (int u = 0; u < n_; ++u)
4740 for (auto v : adj[u]) {
4742 0 <= v and v < n_,
4743 "wtree: value: vertices must be indexed in [0, n)");
4744 // Symmetric adjacency: count each undirected edge once.
4745 if (u < v) {
4746 edges_.emplace_back(u, v);
4748 dsu_.unite(u, v),
4749 "wtree: value: initial graph must form a tree");
4750 }
4751 }
4752 }
4753
4754 // Creates value from `n` and edge list.
4755 // O(n).
4756 value(int n, const std::vector<std::pair<int, int>> &edges)
4757 : n_(n), adj_(n), print_1_based_(false), print_n_(false), dsu_(n) {
4758 edges_.reserve(edges.size());
4759 for (auto [u, v] : edges) {
4760 tgen_ensure(0 <= std::min(u, v) and std::max(u, v) < n,
4761 "wtree: value: vertices must be indexed in [0, n)");
4762 tgen_ensure(dsu_.unite(u, v),
4763 "wtree: value: initial graph must form a tree");
4764 if (u > v)
4765 std::swap(u, v);
4766 edges_.emplace_back(u, v);
4767 adj_[u].insert(v);
4768 adj_[v].insert(u);
4769 }
4770 }
4771 value(int n, const std::set<std::pair<int, int>> &edges)
4772 : value(n, std::vector<std::pair<int, int>>(edges.begin(),
4773 edges.end())) {}
4774 value(int n, const std::initializer_list<std::pair<int, int>> &edges)
4775 : value(n, std::vector<std::pair<int, int>>(edges)) {}
4776
4777 // Creates tree from graph via Kruskal-like random spanning tree.
4778 // Implemented after wgraph definition.
4779 // O(n + m alpha(n)).
4780 value(const typename wgraph<VWeight, EWeight>::value &g);
4781
4782 // Weight type conversion.
4783 // O(n).
4784 template <typename NewVWeight, typename NewEWeight>
4785 typename wtree<NewVWeight, NewEWeight>::value
4786 convert_weight_types() const {
4787 tgen_ensure(!vertex_weights_.has_value() and
4788 !edge_weights_.has_value(),
4789 "wtree: value: cannot convert weight type after "
4790 "assigning weights");
4791
4792 return copy_without_weights<NewVWeight, NewEWeight>();
4793 }
4794
4795 // Fetches number of vertices.
4796 int n() const { return n_; }
4797
4798 // Fetches a const ref. to adjacency list.
4799 const std::vector<std::set<int>> &adj() const { return adj_; }
4800
4801 // Fetches a const ref. to edge list.
4802 const std::vector<std::pair<int, int>> &edges() const { return edges_; }
4803
4804 // Fetches a const ref. to vertex weights.
4806 return vertex_weights_;
4807 }
4808
4809 // Fetches a const ref. to edge weights.
4811 return edge_weights_;
4812 }
4813
4814 // Sets vertex weights.
4815 // O(n).
4816 template <typename NewVWeight = VWeight>
4817 typename wtree<NewVWeight, EWeight>::value set_vertex_weights(
4818 const std::vector<NewVWeight> &vertex_weights) const {
4819 tgen_ensure(static_cast<int>(vertex_weights.size()) == n(),
4820 "wtree: value: must give `n` vertex weights");
4821
4822 auto new_tree = copy_without_weights<NewVWeight, EWeight>();
4823 new_tree.edge_weights_ = edge_weights_;
4824 new_tree.vertex_weights_ = vertex_weights;
4825 return new_tree;
4826 }
4827
4828 // Sets edge weights.
4829 // O(n).
4830 template <typename NewEWeight = EWeight>
4831 typename wtree<VWeight, NewEWeight>::value
4832 set_edge_weights(const std::vector<NewEWeight> &edge_weights) const {
4834 edge_weights.size() == edges().size(),
4835 "wtree: value: must give `edges().size()` edge weights");
4836
4837 auto new_tree = copy_without_weights<VWeight, NewEWeight>();
4838 new_tree.vertex_weights_ = vertex_weights_;
4839 new_tree.edge_weights_ = edge_weights;
4840 return new_tree;
4841 }
4842
4843 // Enables edge-weighted mode before adding weighted edges
4844 // incrementally. The tree must have no edges yet. O(1).
4846 tgen_ensure(edges().size() == 0,
4847 "wtree: value: edge_weighted requires a tree with no "
4848 "edges");
4849 tgen_ensure(!edge_weights_.has_value(),
4850 "wtree: value: tree is already edge-weighted");
4851
4852 edge_weights_ = std::vector<EWeight>();
4853 return *this;
4854 }
4855
4856 // Sets that should print vertex ids 1-based. Does not change stored
4857 // ids; use to_std_1_based() for a 1-based export.
4858 // O(1).
4860 print_1_based_ = true;
4861 return *this;
4862 }
4863
4864 // Prints `n` on a new line before printing the tree.
4865 // O(1).
4867 print_n_ = true;
4868 return *this;
4869 }
4870
4871 // Prints the tree in parent style.
4872 // If root = -1, the root is considered to be 0, and its parent is not
4873 // printed. Otherwise, prints the parent of the root as -1. If root = n,
4874 // randomizes the root. O(1).
4875 value &print_parents(int root = -1) {
4876 tgen_ensure(root == -1 or (0 <= root and root < n()) or root == n(),
4877 "wtree: value: root must be -1, `n`, or in [0, n)");
4878 print_parents_ = root;
4879 return *this;
4880 }
4881
4882 // Shuffles the tree's vertex labels (except those in `indices`,
4883 // which keep their current label) and edge order. The change is
4884 // applied eagerly to the underlying adjacency list, edge list,
4885 // vertex weights and edge weights.
4886 // O(n).
4887 value &shuffle_except(std::set<int> indices) {
4888 // Builds the relabeling: for each vertex `i`, `new_label[i]` is
4889 // its new id. Vertices in `indices` keep their label; the others
4890 // are permuted among themselves.
4891 std::vector<int> new_label(n());
4892 std::vector<int> shuffled;
4893 for (int i = 0; i < n(); ++i) {
4894 if (indices.count(i))
4895 new_label[i] = i;
4896 else
4897 shuffled.push_back(i);
4898 }
4899 std::vector<int> targets = shuffled;
4900 tgen::shuffle(targets.begin(), targets.end());
4901 for (size_t k = 0; k < shuffled.size(); ++k)
4902 new_label[shuffled[k]] = targets[k];
4903
4904 // Rewrites adjacency list with new labels.
4905 std::vector<std::set<int>> new_adj(n());
4906 for (int u = 0; u < n(); ++u)
4907 for (int v : adj_[u])
4908 new_adj[new_label[u]].insert(new_label[v]);
4909 adj_ = std::move(new_adj);
4910
4911 // Rewrites edges with new labels (canonical undirected order).
4912 for (auto &[u, v] : edges_) {
4913 u = new_label[u];
4914 v = new_label[v];
4915 if (u > v)
4916 std::swap(u, v);
4917 }
4918
4919 // Permutes vertex weights to match the new labels.
4920 if (vertex_weights_.has_value()) {
4921 std::vector<VWeight> new_vw(n());
4922 for (int i = 0; i < n(); ++i)
4923 new_vw[new_label[i]] = (*vertex_weights_)[i];
4924 vertex_weights_ = std::move(new_vw);
4925 }
4926
4927 // Rebuilds the dsu so future `add_edge` calls see the new labels.
4928 dsu_ = detail::dsu(n());
4929 for (auto [u, v] : edges_)
4930 dsu_.unite(u, v);
4931
4932 // Shuffles edge order, keeping edge weights aligned.
4933
4934 std::vector<int> perm(edges_.size());
4935 std::iota(perm.begin(), perm.end(), 0);
4936 tgen::shuffle(perm.begin(), perm.end());
4937
4938 std::vector<std::pair<int, int>> new_edges;
4939 std::optional<std::vector<EWeight>> new_ew;
4940 if (edge_weights_.has_value())
4941 new_ew = std::vector<EWeight>();
4942 for (int i : perm) {
4943 new_edges.push_back(edges_[i]);
4944 if (new_ew.has_value())
4945 new_ew->push_back((*edge_weights_)[i]);
4946 }
4947 edges_ = new_edges;
4948 if (new_ew.has_value())
4949 edge_weights_ = new_ew;
4950
4951 return *this;
4952 }
4953
4954 // Shuffles the tree's vertices and edge order.
4955 // O(n).
4956 value &shuffle() { return shuffle_except({}); }
4957
4958 // Adds edge (u, v).
4959 // O(log n) amortized.
4960 value &add_edge(int u, int v, std::optional<EWeight> w = std::nullopt) {
4961 tgen_ensure(0 <= std::min(u, v) and std::max(u, v) < n(),
4962 "wtree: value: vertex ids must be valid");
4963
4964 if (u > v)
4965 std::swap(u, v);
4966
4967 if (adj_[u].count(v))
4968 return *this;
4969
4970 // Validate before mutation so rejected insertions are safe to
4971 // retry.
4972 if (w.has_value()) {
4973 tgen_ensure(edge_weights().has_value(),
4974 "wtree: value: cannot add weighted edge to "
4975 "edge-unweighted tree");
4976 } else
4977 tgen_ensure(!edge_weights().has_value(),
4978 "wtree: value: cannot add unweighted edge to "
4979 "edge-weighted tree");
4980
4981 tgen_ensure(dsu_.unite(u, v),
4982 "wtree: value: added edge must not create a cycle");
4983 adj_[u].insert(v);
4984 adj_[v].insert(u);
4985 edges_.emplace_back(u, v);
4986 if (w.has_value())
4987 edge_weights_->push_back(*w);
4988
4989 return *this;
4990 }
4991
4992 // Links tree with another `rhs`, adding the edge between u (in left
4993 // tree) and v (in right tree). Ids for added vertices are updated
4994 // accordingly.
4995 // O(rhs.n + rhs.m * log n) amortized.
4996 value &link(const value &rhs, int new_u, int new_v,
4997 std::optional<EWeight> new_w = std::nullopt) {
4998 // Keep the right-hand input stable when linking to ourselves.
4999 if (this == &rhs) {
5000 value copy = rhs;
5001 return link(copy, new_u, new_v, new_w);
5002 }
5003
5004 tgen_ensure(0 <= new_u and new_u < n() and 0 <= new_v and
5005 new_v < rhs.n(),
5006 "wtree: value: vertex ids must be valid");
5007
5008 // Edges from right-hand side.
5009 int shift = n();
5010 add_vertices(rhs.n(), rhs.vertex_weights());
5011 for (int i = 0; i < static_cast<int>(rhs.edges().size()); ++i) {
5012 auto [u, v] = rhs.edges()[i];
5013 add_edge(shift + u, shift + v,
5014 rhs.edge_weights().has_value()
5015 ? std::optional<EWeight>((*rhs.edge_weights())[i])
5016 : std::nullopt);
5017 }
5018
5019 // New edge.
5020 add_edge(new_u, shift + new_v, new_w);
5021
5022 return *this;
5023 }
5024
5025 // Glues the tree with another `rhs` such that index_pairs[i].first is
5026 // considered to be the same as index_pairs[i].second. Ids for added
5027 // vertices are updated accordingly.
5028 // O(rhs.n + rhs.m * log n) amortized.
5029 value &glue(const value &rhs,
5030 std::set<std::pair<int, int>> index_pairs) {
5031 // Appending edges must not change the right-hand input or loop
5032 // bound.
5033 if (this == &rhs) {
5034 value copy = rhs;
5035 return glue(copy, std::move(index_pairs));
5036 }
5037
5038 // Checks validity of indices.
5039 std::set<int> idx_left, idx_right;
5040 std::vector<int> right_id_to_left(rhs.n(), -1);
5041 for (auto [l, r] : index_pairs) {
5043 0 <= l and l < n() and 0 <= r and r < rhs.n(),
5044 "wtree: value: vertex indices to glue must be valid");
5045 tgen_ensure(idx_left.count(l) == 0 and idx_right.count(r) == 0,
5046 "wtree: value: must not have repeated indices "
5047 "on the same side to glue");
5048
5049 idx_left.insert(l);
5050 idx_right.insert(r);
5051 right_id_to_left[r] = l;
5052 }
5053
5054 // Computes new ids of right vertices.
5055 std::vector<int> new_right_id(rhs.n(), -1);
5056 int intersection_lt = 0;
5057 std::optional<std::vector<VWeight>> rhs_vertex_weights;
5058 // Preserve weighted mode even when no new vertices are added.
5059 if (rhs.vertex_weights().has_value())
5060 rhs_vertex_weights = std::vector<VWeight>();
5061 for (int i = 0; i < rhs.n(); ++i) {
5062 if (right_id_to_left[i] != -1) {
5063 // Is in intersection.
5064 ++intersection_lt;
5065 new_right_id[i] = right_id_to_left[i];
5066 } else {
5067 // New id.
5068 new_right_id[i] = n() + i - intersection_lt;
5069 if (rhs.vertex_weights().has_value()) {
5070 rhs_vertex_weights->push_back(
5071 (*rhs.vertex_weights())[i]);
5072 }
5073 }
5074 }
5075
5076 // Adds new vertices and edges.
5077 add_vertices(rhs.n() - intersection_lt, rhs_vertex_weights);
5078 for (int i = 0; i < static_cast<int>(rhs.edges().size()); ++i) {
5079 auto [u, v] = rhs.edges()[i];
5080 add_edge(new_right_id[u], new_right_id[v],
5081 rhs.edge_weights().has_value()
5082 ? std::optional<EWeight>((*rhs.edge_weights())[i])
5083 : std::nullopt);
5084 }
5085
5086 return *this;
5087 }
5088 value &glue(const value &rhs,
5089 std::initializer_list<std::pair<int, int>> il) {
5090 return glue(rhs, std::set<std::pair<int, int>>(il));
5091 }
5092
5093 // Glues the tree with another `rhs` at `indices`. That is, idx in
5094 // `indices` are considered to be the same vertex. Ids for added
5095 // vertices are updated accordingly.
5096 // O(rhs.n).
5097 value &glue(const value &rhs, std::set<int> indices) {
5098 std::set<std::pair<int, int>> index_pairs;
5099 for (auto i : indices)
5100 index_pairs.emplace(i, i);
5101 return glue(rhs, index_pairs);
5102 }
5103 value &glue(const value &rhs, const std::initializer_list<int> &il) {
5104 return glue(rhs, std::set<int>(il));
5105 }
5106
5107 // Prints to std::ostream.
5108 // O(n).
5109 friend std::ostream &operator<<(std::ostream &out, const value &val) {
5110 if (val.print_n_)
5111 out << val.n() << '\n';
5112
5113 // Prints vertex weights.
5114 if (val.vertex_weights()) {
5115 for (int i = 0; i < val.n(); ++i) {
5116 if (i > 0)
5117 out << " ";
5118 out << (*val.vertex_weights())[i];
5119 }
5120 out << '\n';
5121 }
5122
5123 tgen_ensure(static_cast<int>(val.edges().size()) == val.n() - 1,
5124 "wtree: value: invalid tree to print (number of edges "
5125 "must be `n` - 1)");
5126
5127 // Prints in parent style.
5128 if (val.print_parents_.has_value()) {
5129 tgen_ensure(!val.edge_weights().has_value(),
5130 "wtree: value: cannot print parent style if edges "
5131 "are weighted");
5132
5133 int root = *val.print_parents_;
5134 bool skip_parent_0 = root == -1;
5135 if (root == -1)
5136 root = 0;
5137 if (root == val.n())
5138 root = next(0, val.n() - 1);
5139
5140 std::vector<int> parent(val.n(), -1);
5141
5142 std::queue<int> q;
5143 std::vector<int> vis(val.n(), false);
5144 q.push(root);
5145 vis[root] = true;
5146
5147 while (q.size()) {
5148 int u = q.front();
5149 q.pop();
5150 for (int v : val.adj()[u])
5151 if (!vis[v]) {
5152 vis[v] = true;
5153 q.push(v);
5154 parent[v] = u;
5155 }
5156 }
5157
5158 if (skip_parent_0) {
5159 for (int i = 1; i < val.n(); ++i) {
5161 parent[i] < i,
5162 "wtree: value: parent of i must be less than i for "
5163 "printing in parent style if root is -1");
5164
5165 if (i > 1)
5166 out << " ";
5167 out << parent[i] + val.print_1_based_;
5168 }
5169 } else {
5170 for (int i = 0; i < val.n(); ++i) {
5171 if (i > 0)
5172 out << " ";
5173 out << (parent[i] == -1 ? -1 : parent[i]) +
5174 val.print_1_based_;
5175 }
5176 }
5177
5178 out << '\n';
5179 return out;
5180 }
5181
5182 // Prints edges.
5183 for (int i = 0; i < static_cast<int>(val.edges().size()); ++i) {
5184 auto [u, v] = val.edges()[i];
5185 out << (u + val.print_1_based_) << " "
5186 << (v + val.print_1_based_);
5187
5188 // Edge weight.
5189 if (val.edge_weights().has_value())
5190 out << " " << (*val.edge_weights())[i];
5191
5192 out << '\n';
5193 }
5194
5195 return out;
5196 }
5197
5198 // Gets a std::pair<n, adj> representing the value (0-based).
5199 // Unaffected by print_1_based().
5200 std::pair<int, std::vector<std::set<int>>> to_std() const {
5201 return std_type(n_, adj_);
5202 }
5203
5204 // Gets a 1-based (n, adj): labels +1, adj size n+1, index 0 unused.
5205 // Unaffected by print_1_based().
5206 std::pair<int, std::vector<std::set<int>>> to_std_1_based() const {
5207 std::vector<std::set<int>> adj(n_ + 1);
5208 for (int u = 0; u < n_; ++u)
5209 for (int v : adj_[u])
5210 adj[u + 1].insert(v + 1);
5211 return std_type(n_, adj);
5212 }
5213
5214 private:
5215 // Copies topology and print options without weights. Preserve edge
5216 // order so newly assigned weights stay aligned with the original edges.
5217 // O(n).
5218 template <typename NewVWeight, typename NewEWeight>
5219 typename wtree<NewVWeight, NewEWeight>::value
5220 copy_without_weights() const {
5221 typename wtree<NewVWeight, NewEWeight>::value new_tree(adj_);
5222 new_tree.edges_ = edges_;
5223 new_tree.print_1_based_ = print_1_based_;
5224 new_tree.print_n_ = print_n_;
5225 new_tree.print_parents_ = print_parents_;
5226 return new_tree;
5227 }
5228
5229 // Adds `k` vertices to the tree (labeled n, n+1, ...n+k-1). Updates
5230 // `n` accordingly. This makes the tree invalid (not a tree anymore).
5231 // O(k) amortized.
5232 value &add_vertices(int k, std::optional<std::vector<VWeight>>
5233 new_vertex_weights = std::nullopt) {
5234 // Check before mutation, and subtract to avoid overflow in n_ + k.
5236 k >= 0,
5237 "wtree: value: number of added vertices must be nonnegative");
5238 tgen_ensure(k <= std::numeric_limits<int>::max() -
5239 static_cast<long long>(n_),
5240 "wtree: value: too many vertices");
5241 if (new_vertex_weights.has_value()) {
5242 tgen_ensure(vertex_weights().has_value(),
5243 "wtree: value: cannot add weighted vertices to "
5244 "vertex-unweighted tree");
5246 static_cast<int>(new_vertex_weights->size()) == k,
5247 "wtree: value: number of vertex weights must be equal "
5248 "to number of added vertices");
5249 } else
5250 tgen_ensure(!vertex_weights().has_value(),
5251 "wtree: value: cannot add unweighted vertices to "
5252 "vertex-weighted tree");
5253
5254 n_ += k;
5255 adj_.resize(n());
5256 if (new_vertex_weights.has_value())
5257 vertex_weights_->insert(vertex_weights_->end(),
5258 new_vertex_weights->begin(),
5259 new_vertex_weights->end());
5260
5261 dsu_.add_elements(k);
5262
5263 return *this;
5264 }
5265 };
5266
5267 // Generates tree value.
5268 // O(n).
5269 value gen() const {
5270 // Constructs adjacency list.
5271 std::vector<std::vector<int>> adj(n_);
5272 for (auto [u, v] : edges_) {
5273 adj[u].push_back(v);
5274 adj[v].push_back(u);
5275 }
5276
5277 std::vector<int> comp_size;
5278 std::vector<std::vector<int>> component_ids;
5279 std::vector<bool> vis(n_, false);
5280 std::queue<int> q;
5281
5282 for (int i = 0; i < n_; ++i) {
5283 if (vis[i])
5284 continue;
5285
5286 vis[i] = true;
5287 q.push(i);
5288 comp_size.push_back(0);
5289 component_ids.emplace_back();
5290 while (q.size()) {
5291 int u = q.front();
5292 q.pop();
5293 ++comp_size.back();
5294 component_ids.back().push_back(u);
5295 for (int v : adj[u]) {
5296 if (!vis[v]) {
5297 vis[v] = true;
5298 q.push(v);
5299 }
5300 }
5301 }
5302 }
5303
5304 // Creates edges connecting the connected components by treating them as
5305 // vertices.
5306 std::vector<std::pair<int, int>> new_edges(edges_.begin(),
5307 edges_.end());
5308 if (comp_size.size() > 1) {
5309 std::vector<int> prufer_values = many_by_distribution(
5310 static_cast<int>(comp_size.size()) - 2, comp_size);
5311 for (auto [u, v] : detail::edges_from_prufer(prufer_values))
5312 new_edges.emplace_back(pick(component_ids[u]),
5313 pick(component_ids[v]));
5314 }
5315
5316 return value(n_, new_edges);
5317 }
5318
5319 // Generates a (not uniformly) random skewed tree.
5320 // Vertex 0 is the root. For each i in 1 .. n-1, parent(i) is
5321 // wnext(i, elongation), i.e. a value in [0, i) with skew controlled by
5322 // elongation (see wnext).
5323 // If elongation is small enough, generates a star (center 0).
5324 // If elongation is large enough, generates a path (endpoints 0 and n-1).
5325 // O(n).
5326 static value gen_skewed(int n, int elongation) {
5327 std::vector<std::pair<int, int>> edges;
5328 for (int i = 1; i < n; ++i)
5329 edges.emplace_back(i, wnext<int>(i, elongation));
5330 return value(n, edges);
5331 }
5332
5333 // Kruskal-like random tree: random vertex pairs until connected.
5334 // Not uniformly random.
5335 // O(n log(n) alpha(n)) expected.
5336 static value gen_kruskal(int n) {
5337 tgen_ensure(n > 0, "wtree: gen_kruskal: n must be positive");
5338 if (n == 1)
5339 return value(1, {});
5340
5341 detail::dsu components(n);
5342 std::vector<std::pair<int, int>> edges;
5343 edges.reserve(n - 1);
5344 while (edges.size() < size_t(n - 1)) {
5345 int u = next(0, n - 1);
5346 int v = next(0, n - 1);
5347 if (u == v)
5348 continue;
5349 if (components.unite(u, v))
5350 edges.emplace_back(u, v);
5351 }
5352 return value(n, edges);
5353 }
5354};
5355
5356/*
5357 * Other types of weighted-ness.
5358 */
5359
5360// Vertex weighted tree.
5361template <typename VWeight> using vtree = wtree<VWeight, int>;
5362
5363// Edge weighted tree.
5364template <typename EWeight> using etree = wtree<int, EWeight>;
5365
5366// Unweighted tree.
5367using tree = wtree<int, int>;
5368
5369/*************
5370 * *
5371 * GRAPH *
5372 * *
5373 *************/
5374
5375namespace detail {
5376
5377// Canonical undirected edge key for duplicate detection; stores (min(u, v),
5378// max(u, v)). O(1).
5379inline uint64_t undirected_edge_key(int u, int v) {
5380 if (u > v)
5381 std::swap(u, v);
5382 return (static_cast<uint64_t>(u) << 32) |
5383 static_cast<uint64_t>(static_cast<uint32_t>(v));
5384}
5385
5386// Directed edge key for duplicate detection; stores (u, v).
5387// O(1).
5388inline uint64_t directed_edge_key(int u, int v) {
5389 return (static_cast<uint64_t>(u) << 32) |
5390 static_cast<uint64_t>(static_cast<uint32_t>(v));
5391}
5392
5393// Maximum number of edges in a simple graph on n vertices.
5394// O(1).
5395inline long long max_graph_edges(int n, bool directed, bool self_loops) {
5396 if (n <= 0)
5397 return 0;
5398 if (directed)
5399 return self_loops ? static_cast<long long>(n) * n
5400 : static_cast<long long>(n) * (n - 1);
5401 // Widen n + 1 too: it overflows int when n == INT_MAX.
5402 return self_loops
5403 ? static_cast<long long>(n) * (static_cast<long long>(n) + 1) / 2
5404 : static_cast<long long>(n) * (n - 1) / 2;
5405}
5406
5407// Uniform random edge for rejection sampling.
5408// O(1) expected.
5409inline std::pair<int, int> get_random_graph_edge(int n, bool directed,
5410 bool self_loops) {
5411 if (directed) {
5412 if (self_loops)
5413 return {next<int>(0, n - 1), next<int>(0, n - 1)};
5414 int u = next<int>(0, n - 1);
5415 int v = next<int>(0, n - 1);
5416 while (u == v)
5417 v = next<int>(0, n - 1);
5418 return {u, v};
5419 }
5420 if (self_loops) {
5421 int u = next<int>(0, n - 1);
5422 int v = next<int>(0, n - 1);
5423 if (u > v)
5424 std::swap(u, v);
5425 return {u, v};
5426 }
5427 int u = next<int>(0, n - 1);
5428 int v = next<int>(0, n - 1);
5429 while (u == v)
5430 v = next<int>(0, n - 1);
5431 if (u > v)
5432 std::swap(u, v);
5433 return {u, v};
5434}
5435
5436// Decodes a linear edge index to (u, v) for an undirected simple graph,
5437// with u < v.
5438// O(log n).
5439inline std::pair<int, int> decode_undirected_simple_edge(int n, long long idx) {
5440 auto base = [&](int u) -> long long {
5441 return static_cast<long long>(u) * (n - 1) -
5442 static_cast<long long>(u) * (u - 1) / 2;
5443 };
5444 int lo = 0, hi = n - 2;
5445 while (lo < hi) {
5446 // Avoid overflow in lo + hi; keep the upper midpoint.
5447 int mid = lo + (hi - lo + 1) / 2;
5448 if (base(mid) <= idx)
5449 lo = mid;
5450 else
5451 hi = mid - 1;
5452 }
5453 return {lo, lo + 1 + int(idx - base(lo))};
5454}
5455
5456// Decodes a linear edge index to (u, v) for an undirected graph with loops,
5457// with u <= v.
5458// O(log n).
5459inline std::pair<int, int> decode_undirected_loops_edge(int n, long long idx) {
5460 auto base = [&](int u) -> long long {
5461 return static_cast<long long>(u) * n -
5462 static_cast<long long>(u) * (u - 1) / 2;
5463 };
5464 int lo = 0, hi = n - 1;
5465 while (lo < hi) {
5466 // Avoid overflow in lo + hi; keep the upper midpoint.
5467 int mid = lo + (hi - lo + 1) / 2;
5468 if (base(mid) <= idx)
5469 lo = mid;
5470 else
5471 hi = mid - 1;
5472 }
5473 return {lo, lo + int(idx - base(lo))};
5474}
5475
5476// Decodes a linear edge index to (u, v) for a directed simple graph (no loops).
5477// O(1).
5478inline std::pair<int, int> decode_directed_simple_edge(int n, long long idx) {
5479 int u = static_cast<int>(idx / (n - 1));
5480 int rem = static_cast<int>(idx % (n - 1));
5481 return {u, rem + (rem >= u)};
5482}
5483
5484// Decodes a linear edge index according to graph mode.
5485// O(log n) for undirected, O(1) for directed.
5486inline std::pair<int, int>
5487decode_graph_edge_index(int n, long long idx, bool directed, bool self_loops) {
5488 if (directed) {
5489 if (self_loops)
5490 return {int(idx / n), int(idx % n)};
5491 return decode_directed_simple_edge(n, idx);
5492 }
5493 if (self_loops)
5494 return decode_undirected_loops_edge(n, idx);
5495 return decode_undirected_simple_edge(n, idx);
5496}
5497
5498} // namespace detail
5499
5500/*
5501 * Graph generator.
5502 *
5503 * Graphs of `n` vertices labeled from 0 to n-1 and `m` edges.
5504 * These are labeled graphs, that is, isomorphism is not taken into
5505 * account. VWeight is the type of vertex weights, and EWeight is the type of
5506 * edge weights. Generator does not generate weights. The weights are to be set
5507 * in the wgraph::value.
5508 */
5509
5510template <typename VWeight, typename EWeight>
5511struct wgraph : gen_base<wgraph<VWeight, EWeight>> {
5512 int n_, m_; // Number of vertices and edges.
5513 std::set<std::pair<int, int>> edges_; // Edges that were set.
5514 bool is_directed_; // If graph is directed.
5515 bool has_self_loops_; // If self-loops are allowed.
5516
5517 // Creates graph generator with `n` vertices and `m` edges.
5518 // Additionally, you can set if the graph is directed and if self loops are
5519 // allowed.
5520 // O(1).
5521 wgraph(int n, int m, bool is_directed = false, bool has_self_loops = false)
5522 : n_(n), m_(m), is_directed_(is_directed),
5523 has_self_loops_(has_self_loops) {
5524 tgen_ensure(n > 0, "wgraph: number of vertices must be positive");
5525 }
5526
5527 // Adds edge between u and v (this edge must be generated).
5528 // O(log m).
5529 wgraph &add_edge(int u, int v) {
5530 tgen_ensure(0 <= std::min(u, v) and std::max(u, v) < n_,
5531 "wgraph: vertices must be indexed in [0, n)");
5532 tgen_ensure(has_self_loops_ or u != v,
5533 "wgraph: self loops are not allowed");
5534
5535 if (!is_directed_ and u > v)
5536 std::swap(u, v);
5537 auto [it, inserted] = edges_.emplace(u, v);
5538 if (static_cast<int>(edges_.size()) > m_) {
5539 // Keep the generator usable after rejecting an extra preset edge.
5540 if (inserted)
5541 edges_.erase(it);
5542 throw detail::error("wgraph: too many edges were added");
5543 }
5544 return *this;
5545 }
5546
5547 // Graph value.
5548 //
5549 // Edges are stored in both directions (if undirected) in adjacency list,
5550 // but only u < v in edge list.
5551 // Optimized for performance (lazy adjacency list; edge-list constructor
5552 // stores edges only).
5554 using std_type = std::tuple<int, int, std::vector<std::set<int>>>;
5555
5556 int n_; // Number of vertices.
5557 mutable std::vector<std::set<int>> adj_; // Adjacency list.
5558 std::vector<std::pair<int, int>> edges_; // Edge list.
5559 bool is_directed_; // If graph is directed.
5560 bool print_1_based_; // If should print vertex ids 1-based (print only).
5561 bool print_nm_; // If should print n and m.
5562 mutable bool adj_built_{
5563 false}; // Lazy cache: true once adj_ is built from edges_; mutable
5564 // so const adj() can populate it.
5565 std::optional<std::vector<VWeight>> vertex_weights_; // Vertex weights.
5566 std::optional<std::vector<EWeight>>
5567 edge_weights_; // Edge weights (in same order as edges_ ).
5568
5569 // Creates value from adjacency list. The edges
5570 // are considered to be directed.
5571 // O(n + m).
5572 value(const std::vector<std::set<int>> &adj, bool is_directed = false)
5573 : n_(static_cast<int>(adj.size())), adj_(adj),
5574 is_directed_(is_directed), print_1_based_(false),
5575 print_nm_(false), adj_built_(true) {
5576 for (int u = 0; u < n_; ++u)
5577 for (auto v : adj[u]) {
5579 0 <= v and v < n_,
5580 "wgraph: value: vertices must be indexed in [0, n)");
5581 // Undirected adjacency is symmetric: count each edge once
5582 // (canonical u <= v). Directed: every out-edge appears
5583 // once.
5584 if (is_directed_ or u <= v)
5585 edges_.emplace_back(u, v);
5586 }
5587 }
5588
5589 // Creates value from `n`, `m`, and edge list. The edges are
5590 // considered to be directed.
5591 // Optimized for performance (lazy adjacency list; unordered_set dedup).
5592 // O(m log m).
5593 value(int n, const std::vector<std::pair<int, int>> &edges = {},
5594 bool is_directed = false)
5595 : n_(n), edges_(), is_directed_(is_directed), print_1_based_(false),
5596 print_nm_(false), adj_built_(false) {
5597 edges_.reserve(edges.size());
5598 std::unordered_set<uint64_t> seen;
5599 seen.reserve(edges.size() * 2 + 1);
5600 for (auto [u, v] : edges) {
5602 0 <= std::min(u, v) and std::max(u, v) < n,
5603 "wgraph: value: vertices must be indexed in [0, n)");
5604 if (!is_directed_ and u > v)
5605 std::swap(u, v);
5606 uint64_t key = is_directed_ ? detail::directed_edge_key(u, v)
5607 : detail::undirected_edge_key(u, v);
5608 if (seen.insert(key).second)
5609 edges_.emplace_back(u, v);
5610 }
5611 }
5612 value(int n, const std::set<std::pair<int, int>> &edges,
5613 bool is_directed = false)
5614 : value(
5615 n,
5616 std::vector<std::pair<int, int>>(edges.begin(), edges.end()),
5617 is_directed) {}
5618 value(int n, const std::initializer_list<std::pair<int, int>> &edges,
5619 bool is_directed = false)
5620 : value(n, std::vector<std::pair<int, int>>(edges), is_directed) {}
5621
5622 // Creates graph from tree (undirected, same edges).
5623 // O(n).
5624 value(const typename wtree<VWeight, EWeight>::value &t)
5625 : value(t.n(), t.edges(), false) {
5626 if (t.vertex_weights().has_value()) {
5627 vertex_weights_ = *t.vertex_weights();
5628 }
5629 if (t.edge_weights().has_value()) {
5630 edge_weights_ = *t.edge_weights();
5631 }
5632 }
5633
5634 // Weight type conversion.
5635 // O(n + m).
5636 template <typename NewVWeight, typename NewEWeight>
5637 typename wgraph<NewVWeight, NewEWeight>::value
5638 convert_weight_types() const {
5639 tgen_ensure(!vertex_weights_.has_value() and
5640 !edge_weights_.has_value(),
5641 "wgraph: value: cannot convert weight type after "
5642 "assigning weights");
5643
5644 return copy_without_weights<NewVWeight, NewEWeight>();
5645 }
5646
5647 // Fetches number of vertices.
5648 int n() const { return n_; }
5649
5650 // Fetches number of edges.
5651 int m() const { return static_cast<int>(edges_.size()); }
5652
5653 // Fetches if graph is directed;
5654 bool is_directed() const { return is_directed_; }
5655
5656 // Fetches a const ref. to adjacency list.
5657 const std::vector<std::set<int>> &adj() const {
5658 ensure_adj_built();
5659 return adj_;
5660 }
5661
5662 // Fetches a const ref. to edge set.
5663 const std::vector<std::pair<int, int>> &edges() const { return edges_; }
5664
5665 // Fetches vertex weights.
5667 return vertex_weights_;
5668 }
5669
5670 // Fetches edge weights.
5672 return edge_weights_;
5673 }
5674
5675 // Sets vertex weights.
5676 // O(n + m).
5677 template <typename NewVWeight = VWeight>
5678 typename wgraph<NewVWeight, EWeight>::value set_vertex_weights(
5679 const std::vector<NewVWeight> &vertex_weights) const {
5680 tgen_ensure(static_cast<int>(vertex_weights.size()) == n(),
5681 "wgraph: value: must give `n` vertex weights");
5682
5683 auto new_graph = copy_without_weights<NewVWeight, EWeight>();
5684 new_graph.edge_weights_ = edge_weights_;
5685 new_graph.vertex_weights_ = vertex_weights;
5686 return new_graph;
5687 }
5688
5689 // Sets edge weights.
5690 // O(n + m).
5691 template <typename NewEWeight = EWeight>
5692 typename wgraph<VWeight, NewEWeight>::value
5693 set_edge_weights(const std::vector<NewEWeight> &edge_weights) const {
5694 tgen_ensure(static_cast<int>(edge_weights.size()) == m(),
5695 "wgraph: value: must give `m` edge weights");
5696
5697 auto new_graph = copy_without_weights<VWeight, NewEWeight>();
5698 new_graph.vertex_weights_ = vertex_weights_;
5699 new_graph.edge_weights_ = edge_weights;
5700 return new_graph;
5701 }
5702
5703 // Enables edge-weighted mode before adding weighted edges
5704 // incrementally. The graph must have no edges yet. O(1).
5706 tgen_ensure(m() == 0,
5707 "wgraph: value: edge_weighted requires a graph with no "
5708 "edges");
5709 tgen_ensure(!edge_weights_.has_value(),
5710 "wgraph: value: graph is already edge-weighted");
5711
5712 edge_weights_ = std::vector<EWeight>();
5713 return *this;
5714 }
5715
5716 // Sets that should print vertex ids 1-based. Does not change stored
5717 // ids; use to_std_1_based() for a 1-based export.
5718 // O(1).
5720 print_1_based_ = true;
5721 return *this;
5722 }
5723
5724 // Prints `n m` on a new line before printing the edges.
5725 // O(1).
5727 print_nm_ = true;
5728 return *this;
5729 }
5730
5731 // Shuffles the graph's vertex labels (except those in `indices`,
5732 // which keep their current label) and edge order. The change is
5733 // applied eagerly to the underlying adjacency list, edge list,
5734 // vertex weights and edge weights.
5735 // O(n + m).
5736 value &shuffle_except(std::set<int> indices) {
5737 ensure_adj_built();
5738 // Builds the relabeling: for each vertex `i`, `new_label[i]` is
5739 // its new id. Vertices in `indices` keep their label; the others
5740 // are permuted among themselves.
5741 std::vector<int> new_label(n());
5742 std::vector<int> shuffled;
5743 for (int i = 0; i < n(); ++i) {
5744 if (indices.count(i))
5745 new_label[i] = i;
5746 else
5747 shuffled.push_back(i);
5748 }
5749 std::vector<int> targets = shuffled;
5750 tgen::shuffle(targets.begin(), targets.end());
5751 for (size_t k = 0; k < shuffled.size(); ++k)
5752 new_label[shuffled[k]] = targets[k];
5753
5754 // Rewrites adjacency list with new labels.
5755 std::vector<std::set<int>> new_adj(n());
5756 for (int u = 0; u < n(); ++u)
5757 for (int v : adj_[u])
5758 new_adj[new_label[u]].insert(new_label[v]);
5759 adj_ = new_adj;
5760
5761 // Rewrites edges with new labels (canonical undirected order).
5762 for (auto &[u, v] : edges_) {
5763 u = new_label[u];
5764 v = new_label[v];
5765 if (!is_directed_ and u > v)
5766 std::swap(u, v);
5767 }
5768
5769 // Permutes vertex weights to match the new labels.
5770 if (vertex_weights_.has_value()) {
5771 std::vector<VWeight> new_vw(n());
5772 for (int i = 0; i < n(); ++i)
5773 new_vw[new_label[i]] = (*vertex_weights_)[i];
5774 vertex_weights_ = new_vw;
5775 }
5776
5777 // Shuffles edge order, keeping edge weights aligned.
5778
5779 std::vector<int> perm(edges_.size());
5780 std::iota(perm.begin(), perm.end(), 0);
5781 tgen::shuffle(perm.begin(), perm.end());
5782
5783 std::vector<std::pair<int, int>> new_edges;
5784 std::optional<std::vector<EWeight>> new_ew;
5785 if (edge_weights_.has_value())
5786 new_ew = std::vector<EWeight>();
5787 for (int i : perm) {
5788 new_edges.push_back(edges_[i]);
5789 if (new_ew.has_value())
5790 new_ew->push_back((*edge_weights_)[i]);
5791 }
5792
5793 edges_ = new_edges;
5794 if (new_ew.has_value())
5795 edge_weights_ = new_ew;
5796
5797 return *this;
5798 }
5799
5800 // Shuffles the graph's vertices and edge order.
5801 // O(n + m).
5802 value &shuffle() { return shuffle_except({}); }
5803
5804 // Adds `k` vertices to the graph (labeled n, n+1, ...n+k-1). Updates
5805 // `n` accordingly.
5806 // O(k) amortized.
5807 value &add_vertices(int k, std::optional<std::vector<VWeight>>
5808 new_vertex_weights = std::nullopt) {
5809 // Check before mutation, and subtract to avoid overflow in n_ + k.
5811 k >= 0,
5812 "wgraph: value: number of added vertices must be nonnegative");
5813 tgen_ensure(k <= std::numeric_limits<int>::max() -
5814 static_cast<long long>(n_),
5815 "wgraph: value: too many vertices");
5816 if (new_vertex_weights.has_value()) {
5817 tgen_ensure(vertex_weights().has_value(),
5818 "wgraph: value: cannot add weighted vertices to "
5819 "vertex-unweighted graph");
5821 static_cast<int>(new_vertex_weights->size()) == k,
5822 "wgraph: value: number of vertex weights must be equal "
5823 "to number of added vertices");
5824 } else
5825 tgen_ensure(!vertex_weights().has_value(),
5826 "wgraph: value: cannot add unweighted vertices to "
5827 "vertex-weighted graph");
5828
5829 ensure_adj_built();
5830 n_ += k;
5831 adj_.resize(n());
5832 if (new_vertex_weights.has_value())
5833 vertex_weights_->insert(vertex_weights_->end(),
5834 new_vertex_weights->begin(),
5835 new_vertex_weights->end());
5836
5837 return *this;
5838 }
5839
5840 // Adds edge (u, v).
5841 // O(log n) amortized.
5842 value &add_edge(int u, int v, std::optional<EWeight> w = std::nullopt) {
5843 ensure_adj_built();
5844 tgen_ensure(0 <= std::min(u, v) and std::max(u, v) < n(),
5845 "wgraph: value: vertex ids must be valid");
5846
5847 if (!is_directed() and u > v)
5848 std::swap(u, v);
5849
5850 if (adj_[u].count(v))
5851 return *this;
5852
5853 // Validate before mutation so rejected insertions are safe to
5854 // retry.
5855 if (w.has_value()) {
5856 tgen_ensure(edge_weights().has_value(),
5857 "wgraph: value: cannot add weighted edge to "
5858 "edge-unweighted graph");
5859 } else
5860 tgen_ensure(!edge_weights().has_value(),
5861 "wgraph: value: cannot add unweighted edge to "
5862 "edge-weighted graph");
5863
5864 adj_[u].insert(v);
5865 if (!is_directed())
5866 adj_[v].insert(u);
5867 edges_.emplace_back(u, v);
5868 if (w.has_value())
5869 edge_weights_->push_back(*w);
5870
5871 return *this;
5872 }
5873
5874 // Links graph with another `rhs`, adding the edge between u (in left
5875 // graph) and v (in right graph). Ids for added vertices are updated
5876 // accordingly.
5877 // O(rhs.n + rhs.m * log n) amortized.
5878 value &link(const value &rhs, int new_u, int new_v,
5879 std::optional<EWeight> new_w = std::nullopt) {
5880 // Keep the right-hand input stable when linking to ourselves.
5881 if (this == &rhs) {
5882 value copy = rhs;
5883 return link(copy, new_u, new_v, new_w);
5884 }
5885
5886 tgen_ensure(0 <= new_u and new_u < n() and 0 <= new_v and
5887 new_v < rhs.n(),
5888 "wgraph: value: vertex ids must be valid");
5889
5892 "wgraph: value: graphs must have the same is_directed value");
5893
5894 // Edges from right-hand side.
5895 int shift = n();
5896 add_vertices(rhs.n(), rhs.vertex_weights());
5897 for (int i = 0; i < rhs.m(); ++i) {
5898 auto [u, v] = rhs.edges()[i];
5899 add_edge(shift + u, shift + v,
5900 rhs.edge_weights().has_value()
5901 ? std::optional<EWeight>((*rhs.edge_weights())[i])
5902 : std::nullopt);
5903 }
5904
5905 // New edge.
5906 add_edge(new_u, shift + new_v, new_w);
5907
5908 return *this;
5909 }
5910
5911 // Glues the graph with another `rhs` such that index_pairs[i].first is
5912 // considered to be the same as index_pairs[i].second. Ids for added
5913 // vertices are updated accordingly.
5914 // O(rhs.n + rhs.m * log n) amortized.
5915 value &glue(const value &rhs,
5916 std::set<std::pair<int, int>> index_pairs) {
5917 // Appending edges must not change the right-hand input or loop
5918 // bound.
5919 if (this == &rhs) {
5920 value copy = rhs;
5921 return glue(copy, std::move(index_pairs));
5922 }
5923
5926 "wgraph: value: graphs must have the same is_directed value");
5927
5928 // Checks validity of indices.
5929 std::set<int> idx_left, idx_right;
5930 std::vector<int> right_id_to_left(rhs.n(), -1);
5931 for (auto [l, r] : index_pairs) {
5933 0 <= l and l < n() and 0 <= r and r < rhs.n(),
5934 "wgraph: value: vertex indices to glue must be valid");
5935 tgen_ensure(idx_left.count(l) == 0 and idx_right.count(r) == 0,
5936 "wgraph: value: must not have repeated indices "
5937 "on the same side to glue");
5938
5939 idx_left.insert(l);
5940 idx_right.insert(r);
5941 right_id_to_left[r] = l;
5942 }
5943
5944 // Computes new ids of right vertices.
5945 std::vector<int> new_right_id(rhs.n(), -1);
5946 int intersection_lt = 0;
5947 std::optional<std::vector<VWeight>> rhs_vertex_weights;
5948 // Preserve weighted mode even when no new vertices are added.
5949 if (rhs.vertex_weights().has_value())
5950 rhs_vertex_weights = std::vector<VWeight>();
5951 for (int i = 0; i < rhs.n(); ++i) {
5952 if (right_id_to_left[i] != -1) {
5953 // Is in intersection.
5954 ++intersection_lt;
5955 new_right_id[i] = right_id_to_left[i];
5956 } else {
5957 // New id.
5958 new_right_id[i] = n() + i - intersection_lt;
5959 if (rhs.vertex_weights().has_value()) {
5960 rhs_vertex_weights->push_back(
5961 (*rhs.vertex_weights())[i]);
5962 }
5963 }
5964 }
5965
5966 // Adds new vertices and edges.
5967 add_vertices(rhs.n() - intersection_lt, rhs_vertex_weights);
5968 for (int i = 0; i < rhs.m(); ++i) {
5969 auto [u, v] = rhs.edges()[i];
5970 add_edge(new_right_id[u], new_right_id[v],
5971 rhs.edge_weights().has_value()
5972 ? std::optional<EWeight>((*rhs.edge_weights())[i])
5973 : std::nullopt);
5974 }
5975
5976 return *this;
5977 }
5978 value &glue(const value &rhs,
5979 std::initializer_list<std::pair<int, int>> il) {
5980 return glue(rhs, std::set<std::pair<int, int>>(il));
5981 }
5982
5983 // Glues the graph with another `rhs` at `indices`. That is, idx in
5984 // `indices` are considered to be the same vertex. Ids for added
5985 // vertices are updated accordingly.
5986 // O(rhs.n + rhs.m * log n) amortized.
5987 value &glue(const value &rhs, std::set<int> indices) {
5988 std::set<std::pair<int, int>> index_pairs;
5989 for (auto i : indices)
5990 index_pairs.emplace(i, i);
5991 return glue(rhs, index_pairs);
5992 }
5993 value &glue(const value &rhs, const std::initializer_list<int> &il) {
5994 return glue(rhs, std::set<int>(il));
5995 }
5996
5997 // Disjoint union.
5998 // Shifts ids from `rhs` graph by n().
5999 // O(rhs.n + rhs.m * log n) amortized.
6001 return glue(rhs, std::set<int>());
6002 }
6003
6004 // Computes uniformly random subgraph of graph with num_edges edges.
6005 // O(n + m).
6006 value &random_subgraph(int num_edges) {
6007 tgen_ensure(num_edges >= 0,
6008 "wgraph: value: number of edges must be nonnegative");
6010 num_edges <= m(),
6011 "wgraph: value: can choose at most `m` edges from graph");
6012
6013 std::vector<std::pair<int, int>> new_edges;
6014 std::optional<std::vector<EWeight>> new_edge_weights;
6015 // Preserve weighted mode even when no edges are selected.
6016 if (edge_weights_.has_value())
6017 new_edge_weights = std::vector<EWeight>();
6018
6019 int left = m();
6020 for (int i = 0; i < m(); ++i) {
6021 if (next(1, left--) <= num_edges) {
6022 new_edges.push_back(edges()[i]);
6023 if (edge_weights_.has_value()) {
6024 new_edge_weights->push_back((*edge_weights())[i]);
6025 }
6026 --num_edges;
6027 }
6028 }
6029
6030 edges_ = new_edges;
6031 edge_weights_ = new_edge_weights;
6032 rebuild_adj_from_edge_list();
6033 return *this;
6034 }
6035
6036 // Computes a random (not uniform) subgraph with `num_edges` edges that
6037 // keeps every connected component connected (does not increase the
6038 // number of connected components).
6039 // 1. Picks a spanning forest via randomized Prim.
6040 // 2. Adds additional edges uniformly at random.
6041 // O(n + m).
6043 tgen_ensure(!is_directed_,
6044 "wgraph: value: random_connected_subgraph is only for "
6045 "undirected graphs");
6047 num_edges <= m(),
6048 "wgraph: value: can choose at most `m` edges from graph");
6049
6050 // Builds an incidence list: for each vertex, the (neighbor, edge
6051 // index) pairs.
6052 std::vector<std::vector<std::pair<int, int>>> incident(n());
6053 for (int i = 0; i < m(); ++i) {
6054 auto [u, v] = edges_[i];
6055 incident[u].emplace_back(v, i);
6056 incident[v].emplace_back(u, i);
6057 }
6058
6059 // Randomized Prim.
6060 std::vector<bool> vis(n(), false);
6061 std::vector<int> queue;
6062 std::vector<bool> in_tree(m(), false);
6063 int forest_edges = 0;
6064
6065 for (int start = 0; start < n(); ++start) {
6066 if (vis[start])
6067 continue;
6068 vis[start] = true;
6069 queue.push_back(start);
6070
6071 while (!queue.empty()) {
6072 int i =
6073 tgen::next<int>(0, static_cast<int>(queue.size()) - 1);
6074 int u = queue[i];
6075 std::swap(queue[i], queue.back());
6076 queue.pop_back();
6077
6078 for (auto [v, edge_idx] : incident[u]) {
6079 if (!vis[v]) {
6080 vis[v] = true;
6081 queue.push_back(v);
6082 in_tree[edge_idx] = true;
6083 ++forest_edges;
6084 }
6085 }
6086 }
6087 }
6089 num_edges >= forest_edges,
6090 "wgraph: value: random_connected_subgraph needs at least "
6091 "`n - c` edges, where `c` is the number of connected "
6092 "components");
6093
6094 // Splits edge indices into forest edges and the rest.
6095 std::vector<int> tree_idx, rest_idx;
6096 for (int i = 0; i < m(); ++i) {
6097 if (in_tree[i])
6098 tree_idx.push_back(i);
6099 else
6100 rest_idx.push_back(i);
6101 }
6102
6103 tgen::shuffle(rest_idx.begin(), rest_idx.end());
6104
6105 std::vector<int> chosen_idx;
6106 chosen_idx.insert(chosen_idx.end(), tree_idx.begin(),
6107 tree_idx.end());
6108 chosen_idx.insert(chosen_idx.end(), rest_idx.begin(),
6109 rest_idx.begin() + num_edges - forest_edges);
6110
6111 detail::tgen_ensure_against_bug(
6112 static_cast<int>(chosen_idx.size()) == num_edges,
6113 "wgraph: value: chose a wrong number of edges");
6114
6115 std::vector<std::pair<int, int>> new_edges;
6116 std::optional<std::vector<EWeight>> new_edge_weights;
6117 if (edge_weights_.has_value())
6118 new_edge_weights = std::vector<EWeight>();
6119 for (int i : chosen_idx) {
6120 new_edges.push_back(edges_[i]);
6121 if (new_edge_weights.has_value())
6122 new_edge_weights->push_back((*edge_weights_)[i]);
6123 }
6124
6125 edges_ = new_edges;
6126 edge_weights_ = new_edge_weights;
6127 rebuild_adj_from_edge_list();
6128 return *this;
6129 }
6130
6131 // Complement. Self loops are maintained.
6132 // O(n^2).
6133 value operator!() const {
6134 tgen_ensure(!edge_weights_.has_value(),
6135 "wgraph: value: cannot compute complement of "
6136 "edge-weighted graph");
6137
6138 value complement = *this;
6139 complement.ensure_adj_built();
6140 std::vector<std::pair<int, int>> compl_edges;
6141 for (int i = 0; i < complement.n_; ++i) {
6142 std::set<int> complement_adj;
6143 for (int j = 0; j < complement.n_; ++j) {
6144 bool add_j = false;
6145 if (j == i and complement.adj_[i].count(j))
6146 add_j = true;
6147 if (j != i and !complement.adj_[i].count(j))
6148 add_j = true;
6149
6150 if (add_j) {
6151 complement_adj.insert(j);
6152 // If i > j and !is_directed(), we don't add the edge.
6153 if (i <= j or complement.is_directed_) {
6154 compl_edges.emplace_back(i, j);
6155 }
6156 }
6157 }
6158 std::swap(complement.adj_[i], complement_adj);
6159 }
6160 std::swap(complement.edges_, compl_edges);
6161
6162 return complement;
6163 }
6164
6165 // Concatenates two values.
6166 // O(N + M log N), N = n + rhs.n, M = m + rhs.m.
6167 value operator+(const value &rhs) const {
6169 "wgraph: value: graphs must have the same "
6170 "is_directed value");
6171
6172 tgen_ensure(vertex_weights().has_value() ==
6173 rhs.vertex_weights().has_value(),
6174 "wgraph: value: cannot concatenate vertex-weighted "
6175 "wgraph to unweighted");
6176 tgen_ensure(edge_weights().has_value() ==
6177 rhs.edge_weights().has_value(),
6178 "wgraph: value: cannot concatenate edge-weighted "
6179 "wgraph to unweighted");
6180
6181 value concat = *this;
6182 concat.glue(rhs, std::set<std::pair<int, int>>());
6183 concat.print_1_based_ = print_1_based_ | rhs.print_1_based_;
6184 concat.print_nm_ = print_nm_ | rhs.print_nm_;
6185
6186 return concat;
6187 }
6188
6189 // Prints to std::ostream.
6190 // O(n + m).
6191 friend std::ostream &operator<<(std::ostream &out, const value &val) {
6192 // Prints `n` and `m`.
6193 if (val.print_nm_)
6194 out << val.n() << " " << val.m() << '\n';
6195
6196 // Prints vertex weights.
6197 if (val.vertex_weights()) {
6198 for (int i = 0; i < val.n(); ++i) {
6199 if (i > 0)
6200 out << " ";
6201 out << (*val.vertex_weights())[i];
6202 }
6203 out << '\n';
6204 }
6205
6206 // Prints edges.
6207 for (int i = 0; i < val.m(); ++i) {
6208 auto [u, v] = val.edges()[i];
6209 out << (u + val.print_1_based_) << " "
6210 << (v + val.print_1_based_);
6211
6212 // Edge weight.
6213 if (val.edge_weights().has_value())
6214 out << " " << (*val.edge_weights())[i];
6215
6216 out << '\n';
6217 }
6218
6219 return out;
6220 }
6221
6222 // Gets a std::tuple<n, m, adj> representing the value (0-based).
6223 // Unaffected by print_1_based().
6224 std::tuple<int, int, std::vector<std::set<int>>> to_std() const {
6225 ensure_adj_built();
6226 return std_type(n_, m(), adj_);
6227 }
6228
6229 // Gets a 1-based (n, m, adj): labels +1, adj size n+1, index 0 unused.
6230 // Unaffected by print_1_based().
6231 std::tuple<int, int, std::vector<std::set<int>>>
6233 ensure_adj_built();
6234 std::vector<std::set<int>> adj(n_ + 1);
6235 for (int u = 0; u < n_; ++u)
6236 for (int v : adj_[u])
6237 adj[u + 1].insert(v + 1);
6238 return std_type(n_, m(), adj);
6239 }
6240
6241 private:
6242 // Preserve the existing cache and edge order. Do not build adjacency
6243 // just to assign weights when the source has no cache yet.
6244 // O(n + m).
6245 template <typename NewVWeight, typename NewEWeight>
6246 typename wgraph<NewVWeight, NewEWeight>::value
6247 copy_without_weights() const {
6248 using new_value = typename wgraph<NewVWeight, NewEWeight>::value;
6249 new_value new_graph =
6250 adj_built_ ? new_value(adj_, is_directed_)
6251 : new_value(n_, std::vector<std::pair<int, int>>(),
6252 is_directed_);
6253 new_graph.edges_ = edges_;
6254 new_graph.print_1_based_ = print_1_based_;
6255 new_graph.print_nm_ = print_nm_;
6256 return new_graph;
6257 }
6258
6259 // Rebuilds adjacency from edges_ after replacing the edge list (e.g.
6260 // subgraph operations).
6261 // O(m log n).
6262 void rebuild_adj_from_edge_list() const {
6263 adj_.assign(n_, {});
6264 for (auto [u, v] : edges_) {
6265 adj_[u].insert(v);
6266 if (!is_directed_)
6267 adj_[v].insert(u);
6268 }
6269 adj_built_ = true;
6270 }
6271
6272 // Builds adj_ from edges_ on first use.
6273 // O(1) if already built; O(m log n) otherwise.
6274 void ensure_adj_built() const {
6275 if (adj_built_)
6276 return;
6277 rebuild_adj_from_edge_list();
6278 }
6279 };
6280
6281 // Adds all edges from `rhs` as preset edges.
6282 // O(rhs.m * log m).
6284 tgen_ensure(is_directed_ == rhs.is_directed(),
6285 "wgraph: graphs must have the same is_directed value");
6286
6287 for (auto [u, v] : rhs.edges())
6288 add_edge(u, v);
6289 return *this;
6290 }
6291
6292 // Generates graph value.
6293 // Optimized for performance: dense no-preset graphs use index sampling;
6294 // otherwise gen_remaining_edges.
6295 // O(n + m log^2 n) expected.
6296 value gen() const {
6297 detail::tgen_ensure_against_bug(static_cast<int>(edges_.size()) <= m_,
6298 "wgraph: too many edges were added");
6299
6300 // All edges already added.
6301 if (static_cast<int>(edges_.size()) == m_)
6302 return value(n_, edges_, is_directed_);
6303
6304 // Splits into two cases to optimize performance.
6305
6306 // No presets and m > max_edges / 2: sample m distinct edge indices.
6307 if (auto indexed = try_gen_by_edge_index())
6308 return *indexed;
6309
6310 // Otherwise: fill preset edges up to m_ with uniform random edges.
6311 return gen_remaining_edges(
6312 std::vector<std::pair<int, int>>(edges_.begin(), edges_.end()));
6313 }
6314
6315 // Gets a (not uniformly) random connected undirected graph.
6316 // 1. Preset edges induce a spanning forest on their components.
6317 // 2. Then, uniformly random edges between components are added.
6318 // 3. Remaining edges are added uniformly at random.
6319 // O(n + m log^2 n) expected.
6321 tgen_ensure(!is_directed_,
6322 "wgraph: get_connected is only for undirected graphs");
6323 tgen_ensure(m_ >= n_ - 1,
6324 "wgraph: connected graph needs at least n - 1 edges");
6325
6326 std::vector<std::pair<int, int>> edges;
6327 edges.reserve(m_);
6328
6329 if (edges_.empty()) {
6330 if (n_ > 1) {
6331 std::vector<int> prufer(n_ - 2);
6332 for (int i = 0; i < n_ - 2; ++i)
6333 prufer[i] = next<int>(0, n_ - 1);
6334 for (auto [u, v] : detail::edges_from_prufer(std::move(prufer)))
6335 edges.emplace_back(u, v);
6336 }
6337 } else {
6338 edges.assign(edges_.begin(), edges_.end());
6339
6340 std::vector<std::vector<int>> adj(n_);
6341 for (auto [u, v] : edges_) {
6342 adj[u].push_back(v);
6343 adj[v].push_back(u);
6344 }
6345
6346 std::vector<int> comp_size;
6347 std::vector<std::vector<int>> component_ids;
6348 std::vector<bool> vis(n_, false);
6349 std::queue<int> q;
6350
6351 for (int i = 0; i < n_; ++i) {
6352 if (vis[i])
6353 continue;
6354
6355 vis[i] = true;
6356 q.push(i);
6357 comp_size.push_back(0);
6358 component_ids.emplace_back();
6359 while (q.size()) {
6360 int u = q.front();
6361 q.pop();
6362 ++comp_size.back();
6363 component_ids.back().push_back(u);
6364 for (int v : adj[u]) {
6365 if (!vis[v]) {
6366 vis[v] = true;
6367 q.push(v);
6368 }
6369 }
6370 }
6371 }
6372
6373 if (component_ids.size() > 1) {
6374 std::vector<int> prufer_values = many_by_distribution(
6375 static_cast<int>(component_ids.size()) - 2, comp_size);
6376 for (auto [u, v] :
6377 detail::edges_from_prufer(std::move(prufer_values)))
6378 edges.emplace_back(pick(component_ids[u]),
6379 pick(component_ids[v]));
6380 }
6381 }
6382
6383 return gen_remaining_edges(std::move(edges));
6384 }
6385
6386 // Gets a (not uniformly) random directed acyclic graph.
6387 // 1. Randomized Kahn (uniform choice among indegree-0 vertices) yields a
6388 // random topological order of the preset edges (which must be acyclic).
6389 // 2. Extra edges are sampled randomly using the order.
6390 // With no preset edges: sample a random graph then orient acyclically.
6391 // Optimized for performance (distinct upper-triangle edge-index sampling;
6392 // rejection instead of pair::distinct for preset edges).
6393 // O(n + m log^2 n) expected.
6395 tgen_ensure(is_directed_,
6396 "wgraph: get_acyclic is only for directed graphs");
6397
6398 if (edges_.empty()) {
6399 std::vector<int> order(n_);
6400 std::iota(order.begin(), order.end(), 0);
6401 for (int i = n_ - 1; i > 0; --i)
6402 std::swap(order[i], order[next(0, i)]);
6403
6404 const long long max_pairs =
6405 static_cast<long long>(n_) * (n_ - 1) / 2;
6406 tgen_ensure(m_ <= max_pairs,
6407 "wgraph: not enough edges to generate");
6408
6409 std::vector<std::pair<int, int>> edges;
6410 edges.reserve(m_);
6411 for (long long idx : distinct_range<long long>(0, max_pairs - 1)
6412 .gen_list(m_)
6413 .to_std()) {
6414 auto [i, j] = detail::decode_undirected_simple_edge(n_, idx);
6415 edges.emplace_back(order[i], order[j]);
6416 }
6417 return value(n_, edges, true);
6418 }
6419
6420 std::vector<std::vector<int>> adj(n_);
6421 std::vector<int> indeg(n_, 0);
6422 for (auto [u, v] : edges_) {
6423 adj[u].push_back(v);
6424 ++indeg[v];
6425 }
6426
6427 std::vector<int> available;
6428 for (int i = 0; i < n_; ++i)
6429 if (indeg[i] == 0)
6430 available.push_back(i);
6431
6432 // Random topological order using randomized Kahn's algorithm.
6433 std::vector<int> order;
6434 while (!available.empty()) {
6435 int idx = next(0, static_cast<int>(available.size()) - 1);
6436 int u = available[idx];
6437 std::swap(available[idx], available.back());
6438 available.pop_back();
6439
6440 order.push_back(u);
6441 for (int v : adj[u])
6442 if (--indeg[v] == 0)
6443 available.push_back(v);
6444 }
6445
6446 tgen_ensure(static_cast<int>(order.size()) == n_,
6447 "wgraph: preset edges contain a directed cycle");
6448
6449 value acyclic(n_, edges_, true);
6450
6451 // Generates final edges.
6452
6453 detail::tgen_ensure_against_bug(acyclic.m() <= m_,
6454 "wgraph: too many edges were added");
6455
6456 if (acyclic.m() < m_) {
6457 std::vector<int> order_pos(n_);
6458 for (int i = 0; i < n_; ++i)
6459 order_pos[order[i]] = i;
6460
6461 std::unordered_set<uint64_t> seen;
6462 seen.reserve(m_ * 2);
6463 for (auto [u, v] : acyclic.edges())
6464 seen.insert(
6465 detail::undirected_edge_key(order_pos[u], order_pos[v]));
6466
6467 const long long max_pairs =
6468 static_cast<long long>(n_) * (n_ - 1) / 2;
6469 while (acyclic.m() < m_) {
6470 std::pair<int, int> edge;
6471 if (!detail::try_generate_distinct(seen, [&] {
6472 long long idx = next<long long>(0, max_pairs - 1);
6473 edge = detail::decode_undirected_simple_edge(n_, idx);
6474 return detail::undirected_edge_key(edge.first,
6475 edge.second);
6476 }))
6477 throw detail::error("wgraph: not enough edges to generate");
6478 acyclic.add_edge(order[edge.first], order[edge.second]);
6479 }
6480 }
6481
6482 return acyclic;
6483 }
6484
6485 // Generates a (not uniformly) random skewed connected graph.
6486 // 1. Builds the same skewed labeled tree as wtree::gen_skewed(n,
6487 // elongation)(root 0, parent(i) = wnext(i, elongation) for i >= 1).
6488 // If is_directed, tree edges are oriented down the tree.
6489 // 2. Adds remaining edges uniformly from eligible ancestor pairs (v, u),
6490 // where v is between 2 and spread parent steps above u.
6491 // If elongation is small, generates a graph with small diameter.
6492 // If elongation is large, generates a graph with large diameter, with
6493 // vertices 0 and n-1 being far apart.
6494 // O(n + m log n) if spread is O(1);
6495 // O(n log n + m log^2 n) expected otherwise.
6496 static value gen_skewed(int n, int m, int elongation, int spread,
6497 bool is_directed = false) {
6498 tgen_ensure(n > 0, "wgraph: number of vertices must be positive");
6500 m >= n - 1,
6501 "wgraph: skewed graph needs at least n - 1 edges to be connected");
6502 tgen_ensure(spread >= 2,
6503 "wgraph: gen_skewed spread must be at least 2");
6504
6505 value skewed(n, {}, is_directed);
6506
6507 std::vector<int> parent(n), depth(n, 0);
6508 parent[0] = 0;
6509 for (int i = 1; i < n; ++i) {
6510 int p = wnext<int>(i, elongation);
6511 parent[i] = p;
6512 depth[i] = depth[p] + 1;
6513 skewed.add_edge(p, i);
6514 }
6515
6516 const int extra = m - (n - 1);
6517 if (extra == 0)
6518 return skewed;
6519
6520 // If spread is large, use binary lifting to find the ancestor.
6521 // Otherwise, enumerate O(n * spread) ancestor edges and sample
6522 // directly.
6523 constexpr int naive_ancestor_spread = 20;
6524
6525 if (spread <= naive_ancestor_spread) {
6526 std::vector<std::pair<int, int>> candidates;
6527 candidates.reserve(n * spread);
6528 for (int u = 0; u < n; ++u) {
6529 int max_k = std::min(spread, depth[u]);
6530 if (max_k < 2)
6531 continue;
6532 int v = parent[u];
6533 for (int k = 2; k <= max_k; ++k) {
6534 v = parent[v];
6535 candidates.emplace_back(v, u);
6536 }
6537 }
6538
6539 tgen_ensure(extra <= static_cast<int>(candidates.size()),
6540 "wgraph: not enough edges to generate");
6541
6542 for (auto [v, u] : choose(candidates, extra))
6543 skewed.add_edge(v, u);
6544 } else {
6545 // Binary lifting.
6546 int lg = 1;
6547 while ((1 << lg) <= n)
6548 ++lg;
6549
6550 std::vector<std::vector<int>> up(lg, std::vector<int>(n));
6551 for (int v = 0; v < n; ++v)
6552 up[0][v] = parent[v];
6553 for (int j = 1; j < lg; ++j)
6554 for (int v = 0; v < n; ++v)
6555 up[j][v] = up[j - 1][up[j - 1][v]];
6556
6557 // Weight each vertex by its number of eligible ancestors, then
6558 // pick one of those ancestors uniformly.
6559 std::vector<int> distribution = depth;
6560 for (int &d : distribution)
6561 d = std::max(0, std::min(spread - 1, d - 1));
6562 weighted_sampler vertex_choice(distribution);
6563 distinct extra_edges([&]() -> std::pair<int, int> {
6564 int u = static_cast<int>(vertex_choice.next());
6565 // Limit distances before sampling: every jump fits the table,
6566 // and walks past the root do not over-weight the root edge.
6567 int k = next(2, std::min(spread, depth[u]));
6568 int v = u;
6569 for (int j = 0; j < lg; ++j)
6570 if (k >> j & 1)
6571 v = up[j][v];
6572 return {v, u};
6573 });
6574
6575 while (skewed.m() < m) {
6576 std::pair<int, int> edge;
6577 try {
6578 edge = extra_edges.gen();
6579 } catch (const std::runtime_error &e) {
6580 if (std::string(e.what()) ==
6581 "tgen: distinct: no more distinct values")
6582 throw detail::error(
6583 "wgraph: not enough edges to generate");
6584 throw e;
6585 }
6586
6587 skewed.add_edge(edge.first, edge.second);
6588 }
6589 }
6590
6591 return skewed;
6592 }
6593
6594 // Generates a random bipartite graph. The first side has vertices
6595 // 0 .. n1-1, the second n1 .. n1+n2-1.
6596 // Uniform when connected is false (distinct cross-edge indices).
6597 // When connected, incremental bipartite spanning tree + rejection fill;
6598 // not uniform over connected bipartite graphs.
6599 // O(n1 + n2 + m log(n1 * n2)) expected.
6600 static value gen_bipartite(int n1, int n2, int m, bool connected = false) {
6601 tgen_ensure(m >= 0, "wgraph: number of edges must be nonnegative");
6602 long long num_edges = 1LL * n1 * n2;
6603 tgen_ensure(m <= num_edges,
6604 "wgraph: bipartite graph has at most n1 * n2 edges");
6605 if (connected)
6607 m >= n1 + n2 - 1,
6608 "wgraph: connected bipartite graph needs at least n1 + n2 - 1 "
6609 "edges");
6610
6611 // Samples distinct cross edges uniformly.
6612 if (!connected) {
6613 std::vector<std::pair<int, int>> edges;
6614 edges.reserve(m);
6615 for (long long idx : distinct_range<long long>(0, num_edges - 1)
6616 .gen_list(m)
6617 .to_std())
6618 edges.emplace_back(static_cast<int>(idx / n2),
6619 n1 + static_cast<int>(idx % n2));
6620 return value(n1 + n2, std::move(edges), false);
6621 }
6622
6623 std::unordered_set<uint64_t> used_edges;
6624 used_edges.reserve(m * 2);
6625 std::vector<std::pair<int, int>> edges;
6626 edges.reserve(m);
6627
6628 auto pack_edge = [](int u, int v) -> uint64_t {
6629 if (u > v)
6630 std::swap(u, v);
6631 return (static_cast<uint64_t>(u) << 32) | static_cast<uint32_t>(v);
6632 };
6633
6634 // Creates a spanning tree.
6635 if (n1 > 0 and n2 > 0) {
6636 std::vector<int> left = {next(0, n1 - 1)};
6637 std::vector<int> right = {next(n1, n1 + n2 - 1)};
6638 std::vector<int> remaining;
6639 left.reserve(n1);
6640 right.reserve(n2);
6641 remaining.reserve(n1 + n2 - 2);
6642
6643 for (int u = 0; u < n1; ++u)
6644 if (u != left[0])
6645 remaining.push_back(u);
6646 for (int v = n1; v < n1 + n2; ++v)
6647 if (v != right[0])
6648 remaining.push_back(v);
6649 shuffle(remaining.begin(), remaining.end());
6650
6651 auto add_tree_edge = [&](int u, int v) {
6652 used_edges.insert(pack_edge(u, v));
6653 edges.emplace_back(u, v);
6654 };
6655 add_tree_edge(left[0], right[0]);
6656
6657 for (int vertex : remaining) {
6658 if (vertex < n1) {
6659 add_tree_edge(vertex, pick(right));
6660 left.push_back(vertex);
6661 } else {
6662 add_tree_edge(pick(left), vertex);
6663 right.push_back(vertex);
6664 }
6665 }
6666 detail::tgen_ensure_against_bug(
6667 used_edges.size() == size_t(n1 + n2 - 1),
6668 "wgraph: invalid bipartite spanning tree size");
6669 }
6670
6671 // Adds remaining edges.
6672 while (edges.size() < size_t(m)) {
6673 int u = next(0, n1 - 1);
6674 int v = next(n1, n1 + n2 - 1);
6675 if (used_edges.insert(pack_edge(u, v)).second)
6676 edges.emplace_back(u, v);
6677 }
6678
6679 return value(n1 + n2, std::move(edges), false);
6680 }
6681
6682 // Random graph on n vertices; each admissible edge independently with
6683 // probability p. Equivalent to sampling m ~ Binomial(N, p) then a uniform
6684 // G(n, m), where N is the number of admissible edges for the given
6685 // directed / self-loop mode.
6686 // O(n^2 (1 + p log^2 n)) expected.
6687 static value gen_np(int n, double p, bool is_directed = false,
6688 bool has_self_loops = false) {
6689 tgen_ensure(n > 0, "wgraph: number of vertices must be positive");
6690 tgen_ensure(p >= 0 and p <= 1, "wgraph: probability must be in [0, 1]");
6691
6692 long long max_edges =
6693 detail::max_graph_edges(n, is_directed, has_self_loops);
6694
6695 long long m = 0;
6696 if (p == 1.0)
6697 m = max_edges;
6698 else if (p > 0.0)
6699 for (long long i = 0; i < max_edges; ++i)
6700 if (next<double>(0.0, 1.0) < p)
6701 ++m;
6702
6703 tgen_ensure(m <= std::numeric_limits<int>::max(),
6704 "wgraph: too many edges to generate");
6705 return wgraph(n, static_cast<int>(m), is_directed, has_self_loops)
6706 .gen();
6707 }
6708
6709 private:
6710 // If this generator has no preset edges and m is large relative to the
6711 // maximum edge count, sample by distinct edge index. Otherwise
6712 // std::nullopt.
6713 // Optimized for performance (index sampling instead of rejection).
6714 // O(m log n).
6715 std::optional<value> try_gen_by_edge_index() const {
6716 if (!edges_.empty())
6717 return std::nullopt;
6718
6719 long long max_edges =
6720 detail::max_graph_edges(n_, is_directed_, has_self_loops_);
6721 if (m_ > max_edges)
6722 throw detail::error("wgraph: not enough edges to generate");
6723 if (max_edges <= 0 or 2LL * m_ <= max_edges)
6724 return std::nullopt;
6725
6726 std::vector<std::pair<int, int>> edges;
6727 edges.reserve(m_);
6728 for (long long idx :
6729 distinct_range<long long>(0, max_edges - 1).gen_list(m_).to_std())
6730 edges.push_back(detail::decode_graph_edge_index(
6731 n_, idx, is_directed_, has_self_loops_));
6732
6733 return value(n_, edges, is_directed_);
6734 }
6735
6736 // Fills `edges` up to m_ with uniform random edges not already present.
6737 // Optimized for performance (uint64 edge keys + try_generate_distinct).
6738 // O(m log^2 n) expected.
6739 value gen_remaining_edges(std::vector<std::pair<int, int>> edges) const {
6740 detail::tgen_ensure_against_bug(static_cast<int>(edges.size()) <= m_,
6741 "wgraph: too many edges were added");
6742
6743 if (static_cast<int>(edges.size()) == m_)
6744 return value(n_, edges, is_directed_);
6745
6746 edges.reserve(m_);
6747
6748 std::unordered_set<uint64_t> seen;
6749 seen.reserve(m_ * 2);
6750 for (auto [u, v] : edges) {
6751 if (!is_directed_ and u > v)
6752 std::swap(u, v);
6753 seen.insert(is_directed_ ? detail::directed_edge_key(u, v)
6754 : detail::undirected_edge_key(u, v));
6755 }
6756
6757 while (static_cast<int>(edges.size()) < m_) {
6758 std::pair<int, int> edge;
6759 if (!detail::try_generate_distinct(seen, [&] {
6760 edge = detail::get_random_graph_edge(n_, is_directed_,
6761 has_self_loops_);
6762 if (!is_directed_ and edge.first > edge.second)
6763 std::swap(edge.first, edge.second);
6764 return is_directed_ ? detail::directed_edge_key(edge.first,
6765 edge.second)
6766 : detail::undirected_edge_key(
6767 edge.first, edge.second);
6768 }))
6769 throw detail::error("wgraph: not enough edges to generate");
6770 edges.emplace_back(edge);
6771 }
6772
6773 return value(n_, edges, is_directed_);
6774 }
6775};
6776
6777// Implementation of wtree::value constructor from wgraph.
6778// O(n + m alpha(n)).
6779template <typename VWeight, typename EWeight>
6780wtree<VWeight, EWeight>::value::value(
6781 const typename wgraph<VWeight, EWeight>::value &g)
6782 : n_(g.n()), adj_(g.n()), print_1_based_(false), print_n_(false),
6783 dsu_(g.n()) {
6784 tgen_ensure(g.n() > 0, "wtree: value: graph must have at least one vertex");
6785 tgen_ensure(!g.is_directed(),
6786 "wtree: value: graph must be undirected to form a tree");
6787
6788 if (g.vertex_weights().has_value())
6789 vertex_weights_ = *g.vertex_weights();
6790 if (g.edge_weights().has_value())
6791 edge_weights_ = std::vector<EWeight>();
6792
6793 if (n_ == 1)
6794 return;
6795
6796 std::vector<int> order(g.m());
6797 std::iota(order.begin(), order.end(), 0);
6798 tgen::shuffle(order.begin(), order.end());
6799
6800 std::vector<std::pair<int, int>> tree_edges;
6801 tree_edges.reserve(n_ - 1);
6802
6803 for (int i : order) {
6804 auto [u, v] = g.edges()[i];
6805 if (!dsu_.unite(u, v))
6806 continue;
6807 if (u > v)
6808 std::swap(u, v);
6809
6810 tree_edges.emplace_back(u, v);
6811 adj_[u].insert(v);
6812 adj_[v].insert(u);
6813 if (edge_weights_.has_value())
6814 edge_weights_->push_back((*g.edge_weights())[i]);
6815 if (static_cast<int>(tree_edges.size()) == n_ - 1)
6816 break;
6817 }
6818
6819 tgen_ensure(static_cast<int>(tree_edges.size()) == n_ - 1,
6820 "wtree: value: graph must be connected to form a tree");
6821
6822 edges_ = std::move(tree_edges);
6823}
6824
6825/*
6826 * Other types of weighted-ness.
6827 */
6828
6829// Vertex weighted graph.
6830template <typename VWeight> using vgraph = wgraph<VWeight, int>;
6831
6832// Edge weighted graph.
6833template <typename EWeight> using egraph = wgraph<int, EWeight>;
6834
6835// Unweighted graph.
6836using graph = wgraph<int, int>;
6837
6838/*
6839 * Standard graphs.
6840 */
6841
6842// Complete.
6843// O(n^2).
6844inline graph::value K(int n) {
6845 tgen_ensure(n > 0, "K: number of vertices must be positive");
6846 // The product can overflow int even when the divided edge count fits.
6847 long long edges = detail::max_graph_edges(n, false, false);
6848 tgen_ensure(edges <= std::numeric_limits<int>::max(),
6849 "K: too many edges to generate");
6850 return graph(n, static_cast<int>(edges)).gen();
6851}
6852
6853// Path.
6854// Path with `n` vertices. The edges of the path are 0 and n-1.
6855// If directed, edges are i -> i+1 for i in [0, n-2).
6856// O(n).
6857inline graph::value P(int n, bool is_directed = false) {
6858 graph g(n, n - 1, is_directed);
6859 for (int i = 0; i + 1 < n; ++i)
6860 g.add_edge(i, i + 1);
6861 return g.gen();
6862}
6863
6864// Cycle.
6865// n >= 3.
6866// If directed, edges are i -> (i+1) % n.
6867// O(n).
6868inline graph::value C(int n, bool is_directed = false) {
6869 tgen_ensure(n >= 3, "graph: cycle size must be at least 3");
6870
6871 graph g(n, n, is_directed);
6872 for (int i = 0; i < n; ++i)
6873 g.add_edge(i, (i + 1) % n);
6874 return g.gen();
6875}
6876
6877// Complete bipartite.
6878// The first side has vertices `0` to `n1-1`, the second side has vertices `n1`
6879// to `n1+n2-1`.
6880// O(n1 * n2).
6881inline graph::value K(int n1, int n2) {
6882 graph g(n1 + n2, static_cast<long long>(n1) * n2);
6883 for (int i = 0; i < n1; ++i)
6884 for (int j = 0; j < n2; ++j)
6885 g.add_edge(i, n1 + j);
6886 return g.gen();
6887}
6888
6889// Star.
6890// The center is vertex 0.
6891// O(n).
6892inline graph::value S(int n) { return K(1, n - 1); }
6893
6894/****************
6895 * *
6896 * GEOMETRY *
6897 * *
6898 ****************/
6899
6900namespace geometry {
6901
6902// Point on the plane with coordinates of type T.
6903template <typename T> struct point {
6904 static_assert(std::is_arithmetic_v<T>,
6905 "point requires an arithmetic coordinate type");
6906
6907 // Dot/cross product type: __int128 for T = long long, long long for other
6908 // integral T, T for floating-point.
6909 using product_t = std::conditional_t<
6910 std::is_same_v<T, long long>, detail::i128,
6911 std::conditional_t<std::is_integral_v<T>, long long, T>>;
6912
6913 // x and y coordinates.
6914 T x_, y_;
6915
6916 // Constructs a point with coordinates x and y.
6917 point(T x = 0, T y = 0) : x_(x), y_(y) {}
6918
6919 // Returns the x coordinate.
6920 T x() const { return x_; }
6921
6922 // Returns the y coordinate.
6923 T y() const { return y_; }
6924
6925 // Exact coordinate equality, consistent with lexicographic ordering.
6926 static bool coord_eq(T a, T b) { return a == b; }
6927
6928 // Lexicographic order (by x, then y).
6929 bool operator<(const point &p) const {
6930 if (!coord_eq(x_, p.x()))
6931 return x_ < p.x();
6932 return y_ < p.y();
6933 }
6934
6935 // Equality of coordinates.
6936 bool operator==(const point &p) const {
6937 return coord_eq(x_, p.x()) and coord_eq(y_, p.y());
6938 }
6939
6940 // Vector addition.
6941 point operator+(const point &p) const {
6942 return point(x_ + p.x(), y_ + p.y());
6943 }
6944
6945 // Vector subtraction.
6946 point operator-(const point &p) const {
6947 return point(x_ - p.x(), y_ - p.y());
6948 }
6949
6950 // Scalar multiplication.
6951 point operator*(T c) const { return point(x_ * c, y_ * c); }
6952
6953 // Dot product.
6954 product_t operator*(const point &p) const {
6955 if constexpr (std::is_floating_point_v<T>) {
6956 return x_ * p.x() + y_ * p.y();
6957 } else {
6958 // Widening alone cannot represent every dot product at the
6959 // coordinate limits. Reject overflow instead of wrapping.
6960 product_t x_product, y_product, result;
6961 tgen_ensure(!__builtin_mul_overflow(x_, p.x(), &x_product),
6962 "geometry: point dot product overflow");
6963 tgen_ensure(!__builtin_mul_overflow(y_, p.y(), &y_product),
6964 "geometry: point dot product overflow");
6965 tgen_ensure(!__builtin_add_overflow(x_product, y_product, &result),
6966 "geometry: point dot product overflow");
6967 return result;
6968 }
6969 }
6970
6971 // Cross product (signed area of the parallelogram).
6972 product_t operator^(const point &p) const {
6973 if constexpr (std::is_floating_point_v<T>)
6974 return x_ * p.y() - y_ * p.x();
6975 else {
6976 // As with dot products, widening alone does not cover all inputs.
6977 product_t x_product, y_product, result;
6978 tgen_ensure(!__builtin_mul_overflow(x_, p.y(), &x_product),
6979 "geometry: point cross product overflow");
6980 tgen_ensure(!__builtin_mul_overflow(y_, p.x(), &y_product),
6981 "geometry: point cross product overflow");
6982 tgen_ensure(!__builtin_sub_overflow(x_product, y_product, &result),
6983 "geometry: point cross product overflow");
6984 return result;
6985 }
6986 }
6987
6988 // Prints the point as "x y".
6989 friend std::ostream &operator<<(std::ostream &out, const point &p) {
6990 return out << p.x() << ' ' << p.y();
6991 }
6992};
6993
6994// Generates n distinct integer points in [min_coord, max_coord]^2 with no three
6995// collinear.
6996// O(n).
6997inline std::vector<point<long long>>
6998random_points_general_position(int n, long long min_coord,
6999 long long max_coord) {
7000 tgen_ensure(n > 0,
7001 "geometry: random_points_general_position: n must be positive");
7002 tgen_ensure(max_coord >= min_coord,
7003 "geometry: random_points_general_position: min_coord must be "
7004 "at most max_coord");
7006 static_cast<detail::i128>(max_coord) - min_coord <=
7007 std::numeric_limits<long long>::max(),
7008 "geometry: random_points_general_position: coordinate range too large");
7009 uint64_t width = max_coord - min_coord;
7010 // Keep the prime-sized pool within the int indices used by shuffle.
7011 tgen_ensure(n <= std::numeric_limits<int>::max() / 2,
7012 "geometry: random_points_general_position: n too large");
7013 uint64_t p = math::prime_from(2ULL * static_cast<unsigned>(n));
7014 tgen_ensure(p - 1 <= static_cast<uint64_t>(std::numeric_limits<int>::max()),
7015 "geometry: random_points_general_position: n too large");
7016
7017 // Requires width >= p - 1 because sheared coordinates lie in [0, p - 1].
7018 tgen_ensure(width >= p - 1,
7019 "geometry: random_points_general_position: coordinate range "
7020 "too small for n");
7021
7022 // Base set: (x, x^-1 mod p) for x = 1, ..., p - 1.
7023 //
7024 // For a line ax + by + c = 0, substituting y = x^-1 gives ax^2 + cx + b = 0
7025 // (for x != 0), a quadratic with at most two roots in F_p. So at most two
7026 // base points lie on any line. x |-> x^-1 is bijective on {1, ..., p - 1},
7027 // so all points are distinct and no three are collinear.
7028 std::vector<uint64_t> x_range(p - 1);
7029 std::iota(x_range.begin(), x_range.end(), uint64_t{1});
7030 shuffle(x_range.begin(), x_range.end());
7031 std::vector<detail::i128> bx(n), by(n);
7032 for (int i = 0; i < n; ++i) {
7033 uint64_t x = x_range[i];
7034 bx[i] = x;
7035 by[i] = math::modular_inverse(x, p);
7036 }
7037
7038 // Randomize placement without breaking general position: compose elementary
7039 // shears in SL(2, F_p), each either [1 r; 0 1] or [1 0; r 1] with
7040 // r in {-2, -1, 1, 2} (mod p). Every shear has determinant 1, so their
7041 // product is invertible. Invertible linear maps preserve collinearity, so
7042 // the image still has no three collinear points.
7043 const int num_shears = 8;
7044 std::vector<detail::i128> lin_x = bx, lin_y = by;
7045
7046 for (int it = 0; it < num_shears; ++it) {
7047 bool vertical_shear = next(2) == 0;
7048 int shear_r = pick({-2, -1, 1, 2});
7049
7050 for (int i = 0; i < n; ++i) {
7051 if (vertical_shear)
7052 lin_x[i] = (lin_x[i] + shear_r * lin_y[i]) % p;
7053 else
7054 lin_y[i] = (lin_y[i] + shear_r * lin_x[i]) % p;
7055
7056 if (lin_x[i] < 0)
7057 lin_x[i] += p;
7058 if (lin_y[i] < 0)
7059 lin_y[i] += p;
7060 }
7061 }
7062
7063 detail::i128 min_x = lin_x[0], max_x = lin_x[0], min_y = lin_y[0],
7064 max_y = lin_y[0];
7065 for (int i = 1; i < n; ++i) {
7066 min_x = std::min(min_x, lin_x[i]);
7067 max_x = std::max(max_x, lin_x[i]);
7068 min_y = std::min(min_y, lin_y[i]);
7069 max_y = std::max(max_y, lin_y[i]);
7070 }
7071
7072 detail::i128 x_shift =
7073 min_coord - min_x +
7074 next<uint64_t>(0, static_cast<uint64_t>(width - (max_x - min_x)));
7075 detail::i128 y_shift =
7076 min_coord - min_y +
7077 next<uint64_t>(0, static_cast<uint64_t>(width - (max_y - min_y)));
7078
7079 std::vector<point<long long>> pts;
7080 for (int i = 0; i < n; ++i)
7081 pts.emplace_back(static_cast<long long>(lin_x[i] + x_shift),
7082 static_cast<long long>(lin_y[i] + y_shift));
7083 return pts;
7084}
7085
7086namespace detail {
7087
7088using i128 = tgen::detail::i128;
7089
7090using u128 = tgen::detail::u128;
7091
7092// A triangle of long long points has doubled area at most (2^64 - 1)^2.
7093// Its magnitude fits in unsigned 128 bits, but not necessarily signed 128.
7094struct signed_area {
7095 u128 magnitude;
7096 int sign;
7097};
7098
7099inline signed_area triangle_area(const point<long long> &a,
7100 const point<long long> &b,
7101 const point<long long> &p) {
7102 i128 dx1 = i128(b.x()) - a.x(), dy1 = i128(b.y()) - a.y();
7103 i128 dx2 = i128(p.x()) - a.x(), dy2 = i128(p.y()) - a.y();
7104 auto magnitude = [](i128 v) -> u128 { return v < 0 ? -v : v; };
7105 u128 first = magnitude(dx1) * magnitude(dy2);
7106 u128 second = magnitude(dy1) * magnitude(dx2);
7107 int first_sign = (dx1 < 0) != (dy2 < 0) ? -1 : 1;
7108 int second_sign = (dy1 < 0) != (dx2 < 0) ? -1 : 1;
7109 if (first_sign != second_sign) {
7110 // These are products from one triangle, so their sum obeys the
7111 // area bound above even when the two terms have opposite signs.
7112 u128 sum = first + second;
7113 return {sum, sum == 0 ? 0 : first_sign};
7114 }
7115 if (first == second)
7116 return {0, 0};
7117 return first > second ? signed_area{first - second, first_sign}
7118 : signed_area{second - first, -first_sign};
7119}
7120
7121// Orientation only: positive iff (a, b, p) are counterclockwise.
7122inline int ccw(const point<long long> &a, const point<long long> &b,
7123 const point<long long> &p) {
7124 return triangle_area(a, b, p).sign;
7125}
7126
7127// Compares a*x with b*y without forming either potentially 192-bit product.
7128// a and b are positive. Divide x by b and y by a: unequal quotients decide
7129// the result; otherwise the remainders are 64-bit and their products fit.
7130inline int compare_weighted_areas(u128 x, uint64_t a, u128 y, uint64_t b) {
7131 u128 qx = x / b, qy = y / a;
7132 if (qx != qy)
7133 return qx > qy ? 1 : -1;
7134 u128 rx = (x % b) * a, ry = (y % a) * b;
7135 return (rx > ry) - (rx < ry);
7136}
7137
7138// Side of the separator through C and D = (wa*A + wb*B)/(wa + wb).
7139// On a tie, perturb wb by a positive infinitesimal: the separating line
7140// rotates about C, placing points on opposite rays from C on opposite sides.
7141inline bool split_on_positive_side(const point<long long> &A,
7142 const point<long long> &B,
7143 const point<long long> &C,
7144 const point<long long> &P, uint64_t wa,
7145 uint64_t wb) {
7146 signed_area a = triangle_area(C, A, P), b = triangle_area(C, B, P);
7147 if (a.sign == 0)
7148 return b.sign > 0;
7149 if (b.sign == 0 or a.sign == b.sign)
7150 return a.sign > 0;
7151 int comparison = compare_weighted_areas(a.magnitude, wa, b.magnitude, wb);
7152 return comparison == 0 ? b.sign > 0 : comparison == a.sign;
7153}
7154
7155// In-place Hamiltonian path on points[left..right-1] with points[left]
7156// start and points[right-1] end.
7157// O(n log n) expected for every valid input, including collinear triples,
7158// over the algorithm's random choices. O(n^2) worst case.
7159inline void conquer(std::vector<point<long long>> &points, int left,
7160 int right) {
7161 if (right - left <= 3)
7162 return;
7163
7164 point<long long> A = points[left], B = points[right - 1];
7165
7166 // If all points are collinear, sort them properly and return.
7167 bool all_collinear = true;
7168 for (int k = left + 1; k < right - 1; ++k) {
7169 if (ccw(A, B, points[k]) != 0) {
7170 all_collinear = false;
7171 break;
7172 }
7173 }
7174 if (all_collinear) {
7175 std::sort(points.begin() + left, points.begin() + right,
7176 [&](const point<long long> &P, const point<long long> &Q) {
7177 return A < B ? P < Q : Q < P;
7178 });
7179 return;
7180 }
7181
7182 // Choses a pivot that is not collinear with A and B.
7183 std::vector<int> candidates;
7184 for (int k = left + 1; k < right - 1; ++k) {
7185 if (ccw(A, B, points[k]) != 0)
7186 candidates.push_back(k);
7187 }
7188 int ci = candidates[next(0, static_cast<int>(candidates.size()) - 1)];
7189 point<long long> C = points[ci];
7190
7191 uint64_t wa = next<uint64_t>(1, std::numeric_limits<uint64_t>::max());
7192 uint64_t wb = next<uint64_t>(1, std::numeric_limits<uint64_t>::max());
7193 bool a_on_positive = ccw(C, A, B) < 0;
7194
7195 // Classify points using a consistent symbolic rotation for exact ties.
7196 auto is_positive = [&](const point<long long> &P) -> bool {
7197 return split_on_positive_side(A, B, C, P, wa, wb);
7198 };
7199
7200 // Holds C at points[right-2] while classifying interior points in
7201 // [left+1, right-3].
7202 if (ci != right - 2)
7203 std::swap(points[ci], points[right - 2]);
7204
7205 int i = left + 1;
7206 int j = right - 3;
7207 while (i < j) {
7208 if (is_positive(points[i]) == a_on_positive)
7209 ++i;
7210 else if (is_positive(points[j]) != a_on_positive)
7211 --j;
7212 else {
7213 std::swap(points[i], points[j]);
7214 ++i;
7215 --j;
7216 }
7217 }
7218
7219 // After partition:
7220 // points[left]=A | (A,C)... | C | (C,B)... | points[right-1]=B.
7221
7222 // After the swap, p is the index of C (pivot between the two subpaths).
7223 int p = i;
7224 if (i == j and is_positive(points[i]) == a_on_positive)
7225 ++p;
7226 std::swap(points[p], points[right - 2]);
7227
7228 // Path A -> C.
7229 conquer(points, left, p + 1);
7230 // Path C -> B.
7231 conquer(points, p, right);
7232}
7233
7234// Samples k sorted distinct integers from [left, right] uniformly.
7235// Optimized for performance (pool partial Fisher–Yates or complement path for
7236// modest ranges; sparse-map fallback otherwise).
7237// O(k log k); O(right - left) memory when the range is modest.
7238inline std::vector<long long>
7239sample_sorted_distinct_in_range(int k, long long left, long long right) {
7240 long long universe = right - left + 1;
7241 std::vector<long long> res;
7242 res.reserve(k);
7243 if (k == 0)
7244 return res;
7245
7246 constexpr long long pool_threshold = 8'000'000;
7247 constexpr long long pool_always_below = 500'000;
7248
7249 if (universe <= pool_threshold and
7250 (universe <= pool_always_below or k >= universe / 4)) {
7251 size_t u = universe;
7252 size_t ks = k;
7253 std::vector<long long> pool(u);
7254 std::iota(pool.begin(), pool.end(), left);
7255 size_t m = ks <= u / 2 ? ks : u - ks;
7256 for (size_t i = 0; i < m; ++i) {
7257 size_t j = next<size_t>(i, u - 1);
7258 std::swap(pool[i], pool[j]);
7259 }
7260 if (ks <= u / 2) {
7261 res.assign(pool.begin(), pool.begin() + ks);
7262 std::sort(res.begin(), res.end());
7263 } else {
7264 std::vector<char> excluded(u, 0);
7265 for (size_t i = 0; i < m; ++i)
7266 excluded[pool[i] - left] = 1;
7267 for (long long v = left; v <= right; ++v)
7268 if (!excluded[v - left])
7269 res.push_back(v);
7270 }
7271 } else {
7272 std::unordered_map<long long, long long> virtual_list;
7273 virtual_list.reserve(k * 2);
7274 for (long long i = 0; i < k; ++i) {
7275 long long j = next<long long>(i, universe - 1);
7276 long long vi = virtual_list.count(i) ? virtual_list[i] : i;
7277 long long vj = virtual_list.count(j) ? virtual_list[j] : j;
7278 virtual_list[j] = vi;
7279 virtual_list[i] = vj;
7280 res.push_back(virtual_list[i] + left);
7281 }
7282 std::sort(res.begin(), res.end());
7283 }
7284 return res;
7285}
7286
7287// Valtr-style signed edge components along one axis from n sorted distinct
7288// coordinates. The n differences sum to zero.
7289inline std::vector<long long>
7290valtr_edge_components(const std::vector<long long> &sorted_coords) {
7291 int n = static_cast<int>(sorted_coords.size());
7292 std::vector<long long> left, right;
7293 left.reserve(n / 2);
7294 right.reserve(n / 2);
7295 for (int i = 1; i + 1 < n; ++i) {
7296 if (next(2) == 0)
7297 left.push_back(sorted_coords[i]);
7298 else
7299 right.push_back(sorted_coords[i]);
7300 }
7301 long long lo = sorted_coords.front(), hi = sorted_coords.back();
7302 std::vector<long long> seq;
7303 seq.reserve(n + 1);
7304 seq.push_back(lo);
7305 for (long long v : left)
7306 seq.push_back(v);
7307 seq.push_back(hi);
7308 for (auto it = right.rbegin(); it != right.rend(); ++it)
7309 seq.push_back(*it);
7310 seq.push_back(lo);
7311 std::vector<long long> comps(n);
7312 for (int i = 0; i < n; ++i)
7313 comps[i] = seq[i + 1] - seq[i];
7314 return comps;
7315}
7316
7317// Drops boundary vertices that are collinear with their cyclic neighbors.
7318// O(m), m = |points|.
7319inline std::vector<point<long long>>
7320simplify_strict_boundary(std::vector<point<long long>> points) {
7321 int n = static_cast<int>(points.size());
7322 if (n < 3)
7323 return points;
7324
7325 std::vector<point<long long>> strict_points;
7326 strict_points.reserve(n);
7327 for (int i = 0; i < n; ++i) {
7328 if (ccw(points[(i + n - 1) % n], points[i], points[(i + 1) % n]) != 0)
7329 strict_points.push_back(points[i]);
7330 }
7331 return strict_points;
7332}
7333
7334// Picks k evenly spaced vertices along a longer cyclic boundary.
7335// O(k).
7336inline std::vector<point<long long>>
7337subsample_boundary(const std::vector<point<long long>> &points, int k) {
7338 int n = static_cast<int>(points.size());
7339 if (n <= k)
7340 return points;
7341
7342 std::vector<point<long long>> sampled_points;
7343 sampled_points.reserve(k);
7344 for (int i = 0; i < k; ++i)
7345 sampled_points.push_back(
7346 points[static_cast<size_t>((static_cast<i128>(i) * n) / k)]);
7347 return sampled_points;
7348}
7349
7350// Random translation so the polygon lies in the box.
7351// O(|points|).
7352inline void place_inside_box(std::vector<point<long long>> &points,
7353 long long min_coord, long long max_coord) {
7354 long long width = max_coord - min_coord + 1;
7355
7356 i128 min_x = points[0].x(), max_x = points[0].x();
7357 i128 min_y = points[0].y(), max_y = points[0].y();
7358 for (const point<long long> &p : points) {
7359 min_x = std::min(min_x, static_cast<i128>(p.x()));
7360 max_x = std::max(max_x, static_cast<i128>(p.x()));
7361 min_y = std::min(min_y, static_cast<i128>(p.y()));
7362 max_y = std::max(max_y, static_cast<i128>(p.y()));
7363 }
7364
7365 i128 span_x = max_x - min_x;
7366 i128 span_y = max_y - min_y;
7367 // Random slack keeps the polygon inside the box without filling it.
7368 i128 shift_x =
7369 min_coord - min_x +
7370 next<long long>(0, width - 1 - static_cast<long long>(span_x));
7371 i128 shift_y =
7372 min_coord - min_y +
7373 next<long long>(0, width - 1 - static_cast<long long>(span_y));
7374
7375 for (point<long long> &p : points)
7376 p = point<long long>(static_cast<long long>(p.x() + shift_x),
7377 static_cast<long long>(p.y() + shift_y));
7378}
7379
7380// Random cyclic shift.
7381// O(|points|).
7382inline void randomize_cyclic_shift(std::vector<point<long long>> &points) {
7383 int rot = next(static_cast<int>(points.size()));
7384 if (rot > 0)
7385 std::rotate(points.begin(), points.begin() + rot, points.end());
7386}
7387
7388// Valtr walk for m edges; bbox minimum translated to the origin.
7389// O(m log m).
7390inline std::vector<point<long long>>
7391valtr_vertices(int m, const std::vector<long long> &x_comp,
7392 std::vector<long long> y_comp) {
7393 shuffle(y_comp.begin(), y_comp.end());
7394
7395 std::vector<point<long long>> edges(m);
7396 // Upper half-plane (positive y, or y = 0 and x > 0) sorts before lower.
7397 auto upper = [](const point<long long> &p) {
7398 return p.y() > 0 or (p.y() == 0 and p.x() > 0);
7399 };
7400 for (int i = 0; i < m; ++i)
7401 edges[i] = point<long long>(x_comp[i], y_comp[i]);
7402
7403 std::sort(edges.begin(), edges.end(),
7404 [&upper](const point<long long> &a, const point<long long> &b) {
7405 bool au = upper(a), bu = upper(b);
7406 if (au != bu)
7407 return au;
7408 auto cross = a ^ b;
7409 if (cross != 0)
7410 return cross > 0;
7411 return (a * a) < (b * b);
7412 });
7413
7414 // Prefix-sum the sorted edge vectors to obtain vertex coordinates.
7415 i128 cur_x = 0, cur_y = 0;
7416 std::vector<i128> px(m), py(m);
7417 for (int i = 0; i < m; ++i) {
7418 px[i] = cur_x;
7419 py[i] = cur_y;
7420 cur_x += edges[i].x();
7421 cur_y += edges[i].y();
7422 }
7423 tgen::detail::tgen_ensure_against_bug(
7424 cur_x == 0 and cur_y == 0,
7425 "geometry: random_convex_polygon: walk did not close");
7426
7427 i128 min_x = px[0], min_y = py[0];
7428 for (int i = 1; i < m; ++i) {
7429 min_x = std::min(min_x, px[i]);
7430 min_y = std::min(min_y, py[i]);
7431 }
7432
7433 // Shift so the bbox minimum is at the origin.
7434 std::vector<point<long long>> points;
7435 points.reserve(m);
7436 for (int i = 0; i < m; ++i)
7437 points.emplace_back(px[i] - min_x, py[i] - min_y);
7438 return points;
7439}
7440
7441} // namespace detail
7442
7443// Generates n vertices of a convex integer polygon inside a box.
7444// If strict is true, boundary vertices are guaranteed non-collinear when
7445// generation succeeds; retry count depends on n and width.
7446// Always returns points in counterclockwise order.
7447// O(n log n).
7448inline std::vector<point<long long>>
7449random_convex_polygon(int n, long long min_coord, long long max_coord,
7450 bool strict = false) {
7451 tgen_ensure(n >= 3,
7452 "geometry: random_convex_polygon: n must be at least 3");
7453 tgen_ensure(max_coord >= min_coord,
7454 "geometry: random_convex_polygon: min_coord must be at most "
7455 "max_coord");
7456 tgen_ensure(static_cast<detail::i128>(max_coord) - min_coord + 1 <=
7457 std::numeric_limits<long long>::max(),
7458 "geometry: random_convex_polygon: coordinate range too large");
7459 long long width = max_coord - min_coord + 1;
7461 width >= n,
7462 "geometry: random_convex_polygon: coordinate range too small for n");
7463
7464 // Valtr walk size: n in weak mode; strict mode uses a larger grid so
7465 // collinear removal still leaves at least n vertices to subsample.
7466 int num_coords = n;
7467 if (strict) {
7468 // Extra grid lines beyond n: at least 100 (small-n headroom), about
7469 // n/1000 for large n, and never more than width - n.
7470 int extra = width <= n ? 0
7471 : static_cast<int>(std::min<long long>(
7472 std::max(100, n / 1000), width - n));
7473 num_coords = n + extra;
7474 }
7475
7476 // Strict mode retries coordinate sampling when simplification leaves < n
7477 // vertices; weak mode has no failure path, so one attempt always suffices.
7478 const int max_attempts = strict ? 32 : 1;
7479 for (int i = 0; i < max_attempts; ++i) {
7480 // Build a convex lattice polygon on [0, width - 1]^2, then translate.
7481 std::vector<long long> x_sorted =
7482 detail::sample_sorted_distinct_in_range(num_coords, 0, width - 1);
7483 std::vector<long long> y_sorted =
7484 detail::sample_sorted_distinct_in_range(num_coords, 0, width - 1);
7485 std::vector<long long> x_comp = detail::valtr_edge_components(x_sorted);
7486 std::vector<long long> y_comp = detail::valtr_edge_components(y_sorted);
7487
7488 std::vector<point<long long>> points =
7489 detail::valtr_vertices(num_coords, x_comp, std::move(y_comp));
7490
7491 if (strict) {
7492 std::vector<point<long long>> simplified =
7493 detail::simplify_strict_boundary(std::move(points));
7494 // Tight boxes can leave too few vertices -> resample coordinates.
7495 if (static_cast<int>(simplified.size()) < n)
7496 continue;
7497
7498 points = detail::subsample_boundary(simplified, n);
7499 }
7500
7501 detail::place_inside_box(points, min_coord, max_coord);
7502 detail::randomize_cyclic_shift(points);
7503 return points;
7504 }
7505
7506 // Generation failed.
7507 throw tgen::detail::error(
7508 "geometry: random_convex_polygon: generation failed: coordinate "
7509 "range too small for n");
7510}
7511
7512// Random simple polygon through given distinct points.
7513// Collinear triples are allowed; fails if all points are collinear.
7514// Always returns vertices in counterclockwise order.
7515// O(n log n) expected for every valid input, including collinear triples,
7516// over the algorithm's random choices. O(n^2) worst case.
7518 const std::vector<point<long long>> &points) {
7519 int n = static_cast<int>(points.size());
7520 tgen_ensure(n >= 3,
7521 "geometry: random_simple_polygon_through_points: need at "
7522 "least 3 points");
7524 static_cast<int>(
7525 std::set<point<long long>>(points.begin(), points.end()).size()) ==
7526 n,
7527 "geometry: random_simple_polygon_through_points: points must "
7528 "be distinct");
7529
7530 int idx_a = 0, idx_b = 0;
7531 for (int i = 1; i < n; ++i) {
7532 if (points[i] < points[idx_a])
7533 idx_a = i;
7534 if (points[idx_b] < points[i])
7535 idx_b = i;
7536 }
7537 point<long long> A = points[idx_a], B = points[idx_b];
7538
7539 bool all_collinear = true;
7540 for (int i = 0; i < n; ++i) {
7541 if (i == idx_a or i == idx_b)
7542 continue;
7543 if (detail::ccw(A, B, points[i]) != 0) {
7544 all_collinear = false;
7545 break;
7546 }
7547 }
7548 tgen_ensure(!all_collinear,
7549 "geometry: random_simple_polygon_through_points: all points "
7550 "are collinear; no simple polygon exists");
7551
7552 // Keep points collinear with AB on the chain that has no other points on
7553 // its side, so AB is split through those vertices instead of crossing them
7554 // later.
7555 int negative_count = 0;
7556 for (int i = 0; i < n; ++i) {
7557 if (i == idx_a or i == idx_b)
7558 continue;
7559 if (detail::ccw(A, B, points[i]) < 0)
7560 ++negative_count;
7561 }
7562
7563 std::vector<point<long long>> chain;
7564 chain.push_back(A);
7565 int left_count = 0;
7566 for (int i = 0; i < n; ++i) {
7567 if (i == idx_a or i == idx_b)
7568 continue;
7569 int side = detail::ccw(A, B, points[i]);
7570 if (side < 0 or (side == 0 and negative_count == 0)) {
7571 chain.push_back(points[i]);
7572 ++left_count;
7573 }
7574 }
7575 chain.push_back(B);
7576 for (int i = 0; i < n; ++i) {
7577 if (i == idx_a or i == idx_b)
7578 continue;
7579 int side = detail::ccw(A, B, points[i]);
7580 if (side > 0 or (side == 0 and negative_count != 0))
7581 chain.push_back(points[i]);
7582 }
7583 chain.push_back(A);
7584
7585 int n1 = 2 + left_count;
7586 // Upper chain: A -> B.
7587 detail::conquer(chain, 0, n1);
7588 // Lower chain: B -> A.
7589 detail::conquer(chain, n1 - 1, static_cast<int>(chain.size()));
7590
7591 // Cyclic vertex order: chain[1..n1) then chain[n1..end) (skip each path's
7592 // start vertex).
7593 std::vector<point<long long>> poly;
7594 poly.insert(poly.end(), chain.begin() + 1, chain.begin() + n1);
7595 poly.insert(poly.end(), chain.begin() + n1, chain.end());
7596 return poly;
7597}
7598
7599namespace detail {
7600
7601// Samples n distinct integer points in [min_coord, max_coord]^2.
7602// O(n log n).
7603inline std::vector<point<long long>>
7604random_distinct_points_in_box(int n, long long min_coord, long long max_coord) {
7605 long long width = max_coord - min_coord;
7606 // Promote before adding one: width may already equal LLONG_MAX.
7607 i128 side_128 = i128(width) + 1;
7608 i128 universe = side_128 * side_128;
7609 tgen_ensure(universe <= std::numeric_limits<long long>::max(),
7610 "geometry: random_simple_polygon: coordinate range too large");
7611 long long side = static_cast<long long>(side_128);
7612 tgen_ensure(universe >= n,
7613 "geometry: random_simple_polygon: coordinate range too small "
7614 "for n distinct points");
7615
7616 // Decodes a linear grid key (x * side + y) to a point.
7617 auto decode = [&](long long key) -> point<long long> {
7618 return point<long long>(min_coord + key / side, min_coord + key % side);
7619 };
7620
7621 // Repeats until all generated points are not collinear.
7622 // Runs O(1) expected times.
7623 while (true) {
7624 std::vector<long long> keys =
7625 distinct_range<long long>(0, static_cast<long long>(universe - 1))
7626 .gen_list(n)
7627 .to_std();
7628
7629 std::vector<point<long long>> points;
7630 points.reserve(n);
7631 for (long long key : keys)
7632 points.push_back(decode(key));
7633
7634 // Checks if the points are not all collinear.
7635 for (int i = 2; i < n; ++i) {
7636 if (ccw(points[0], points[1], points[i]) != 0)
7637 return points;
7638 }
7639 }
7640}
7641
7642// Axis-aligned edge data for a CCW polygon (interior on the left).
7643// O(1).
7644struct ortho_poly_edge {
7645 long long len;
7646 bool horiz;
7647 long long fixed;
7648 long long lo, hi;
7649 int out_x, out_y;
7650};
7651
7652// True if a, b, c lie on one horizontal or vertical line.
7653// O(1).
7654inline bool ortho_axis_collinear(const point<long long> &a,
7655 const point<long long> &b,
7656 const point<long long> &c) {
7657 return (a.x() == b.x() and b.x() == c.x()) or
7658 (a.y() == b.y() and b.y() == c.y());
7659}
7660
7661// Edge i of poly: orientation, span, exterior normal.
7662// O(1).
7663inline ortho_poly_edge
7664ortho_analyze_edge(const std::vector<point<long long>> &poly, int i) {
7665 int m = static_cast<int>(poly.size());
7666 point<long long> a = poly[i], b = poly[(i + 1) % m];
7667 ortho_poly_edge e{};
7668 if (a.y() == b.y()) {
7669 e.horiz = true;
7670 e.fixed = a.y();
7671 e.lo = std::min(a.x(), b.x());
7672 e.hi = std::max(a.x(), b.x());
7673 e.out_x = 0;
7674 e.out_y = a.x() < b.x() ? -1 : 1;
7675 } else {
7676 e.fixed = a.x();
7677 e.lo = std::min(a.y(), b.y());
7678 e.hi = std::max(a.y(), b.y());
7679 e.out_x = a.y() < b.y() ? 1 : -1;
7680 }
7681 e.len = e.hi - e.lo;
7682 return e;
7683}
7684
7685// True if open axis-aligned segments (a, b) and (c, d) properly cross or
7686// overlap (excluding shared endpoints).
7687// O(1).
7688inline bool ortho_open_seg_cross(const point<long long> &a,
7689 const point<long long> &b,
7690 const point<long long> &c,
7691 const point<long long> &d) {
7692 if (a.y() == b.y() and c.y() == d.y()) {
7693 if (a.y() != c.y())
7694 return false;
7695 long long lo1 = std::min(a.x(), b.x()), hi1 = std::max(a.x(), b.x());
7696 long long lo2 = std::min(c.x(), d.x()), hi2 = std::max(c.x(), d.x());
7697 return lo1 < hi2 and lo2 < hi1;
7698 }
7699 if (a.x() == b.x() and c.x() == d.x()) {
7700 if (a.x() != c.x())
7701 return false;
7702 long long lo1 = std::min(a.y(), b.y()), hi1 = std::max(a.y(), b.y());
7703 long long lo2 = std::min(c.y(), d.y()), hi2 = std::max(c.y(), d.y());
7704 return lo1 < hi2 and lo2 < hi1;
7705 }
7706 if (a.y() == b.y() and c.x() == d.x()) {
7707 long long hx = a.y(), vx = c.x();
7708 long long hlo = std::min(a.x(), b.x()), hhi = std::max(a.x(), b.x());
7709 long long vlo = std::min(c.y(), d.y()), vhi = std::max(c.y(), d.y());
7710 return hlo < vx and vx < hhi and vlo < hx and hx < vhi;
7711 }
7712 if (a.x() == b.x() and c.y() == d.y()) {
7713 long long vx = a.x(), hy = c.y();
7714 long long vlo = std::min(a.y(), b.y()), vhi = std::max(a.y(), b.y());
7715 long long hlo = std::min(c.x(), d.x()), hhi = std::max(c.x(), d.x());
7716 return vlo < hy and hy < vhi and hlo < vx and vx < hhi;
7717 }
7718 return false;
7719}
7720
7721// Integral ray-crossing point-in-polygon.
7722// O(|poly|).
7723inline bool ortho_point_inside(const std::vector<point<long long>> &poly,
7724 point<long long> p) {
7725 int m = static_cast<int>(poly.size());
7726 bool inside = false;
7727 for (int i = 0, j = m - 1; i < m; j = i++) {
7728 point<long long> a = poly[i], b = poly[j];
7729 if ((a.y() > p.y()) != (b.y() > p.y())) {
7730 i128 x_cross = i128(b.x() - a.x()) * (p.y() - a.y()) -
7731 i128(p.x() - a.x()) * (b.y() - a.y());
7732 if ((a.y() < b.y()) ? x_cross > 0 : x_cross < 0)
7733 inside = !inside;
7734 }
7735 }
7736 return inside;
7737}
7738
7739// True if p lies strictly in the open segment (a, b).
7740// O(1).
7741inline bool ortho_point_strictly_interior(point<long long> p,
7742 point<long long> a,
7743 point<long long> b) {
7744 if (a.y() == b.y()) {
7745 if (p.y() != a.y())
7746 return false;
7747 long long lo = std::min(a.x(), b.x()), hi = std::max(a.x(), b.x());
7748 return lo < p.x() and p.x() < hi;
7749 }
7750 if (a.x() == b.x()) {
7751 if (p.x() != a.x())
7752 return false;
7753 long long lo = std::min(a.y(), b.y()), hi = std::max(a.y(), b.y());
7754 return lo < p.y() and p.y() < hi;
7755 }
7756 return false;
7757}
7758
7759// True if p lies on the closed segment [a, b].
7760// O(1).
7761inline bool ortho_point_on_segment(point<long long> p, point<long long> a,
7762 point<long long> b) {
7763 return p == a or p == b or ortho_point_strictly_interior(p, a, b);
7764}
7765
7766// True if splicing add between A and B on edge_i is valid: no vertex of add
7767// coincides with poly, no boundary self-contact (forward or reverse
7768// T-junctions, collinear overlaps), new segments do not cross other boundary
7769// edges, and inward notches keep all of add inside poly.
7770// O(|poly|), assuming |add| is O(1).
7771inline bool ortho_bump_valid(const std::vector<point<long long>> &poly,
7772 point<long long> A, point<long long> B,
7773 const std::vector<point<long long>> &add,
7774 int edge_i, bool inward) {
7775 int m = static_cast<int>(poly.size());
7776
7777 for (point<long long> v : add)
7778 for (point<long long> q : poly)
7779 if (v == q)
7780 return false;
7781
7782 // Forward T-junction: new vertex on a non-incident edge interior, or on
7783 // edge_i but outside the replaced subsegment [A, B].
7784 for (point<long long> v : add) {
7785 for (int j = 0; j < m; ++j) {
7786 point<long long> c = poly[j], d = poly[(j + 1) % m];
7787 if (j == edge_i) {
7788 if (ortho_point_on_segment(v, c, d) and
7789 !ortho_point_on_segment(v, A, B))
7790 return false;
7791 } else if (ortho_point_strictly_interior(v, c, d)) {
7792 return false;
7793 }
7794 }
7795 }
7796
7797 auto seg_ok = [&](point<long long> s0, point<long long> s1) {
7798 for (int j = 0; j < m; ++j) {
7799 if (j == edge_i)
7800 continue;
7801 point<long long> c = poly[j], d = poly[(j + 1) % m];
7802 if (ortho_open_seg_cross(s0, s1, c, d))
7803 return false;
7804 }
7805 for (int k = 0; k < m; ++k) {
7806 point<long long> q = poly[k];
7807 if (q == s0 or q == s1 or q == A or q == B)
7808 continue;
7809 if (ortho_point_strictly_interior(q, s0, s1))
7810 return false;
7811 }
7812 return true;
7813 };
7814
7815 point<long long> prev = A;
7816 for (point<long long> v : add) {
7817 if (!seg_ok(prev, v))
7818 return false;
7819 prev = v;
7820 }
7821 if (!seg_ok(prev, B))
7822 return false;
7823
7824 if (inward) {
7825 for (point<long long> v : add)
7826 if (!ortho_point_inside(poly, v))
7827 return false;
7828 }
7829
7830 return true;
7831}
7832
7833// Splices a rectangular tab or notch on edge edge_i over [lo, hi], extending
7834// depth units perpendicular to the edge.
7835// O(|poly|).
7836inline bool ortho_bump_edge(std::vector<point<long long>> &poly, int edge_i,
7837 const ortho_poly_edge &e, long long lo,
7838 long long hi, long long depth, bool inward,
7839 size_t max_vertices) {
7840 int m = static_cast<int>(poly.size());
7841 point<long long> A = poly[edge_i], B = poly[(edge_i + 1) % m];
7842
7843 int step_x = inward ? -e.out_x : e.out_x;
7844 int step_y = inward ? -e.out_y : e.out_y;
7845
7846 std::vector<point<long long>> add;
7847 if (e.horiz) {
7848 long long y = e.fixed, y2 = y + step_y * depth;
7849 if (A.x() < B.x()) {
7850 if (lo > A.x())
7851 add.emplace_back(lo, y);
7852 add.emplace_back(lo, y2);
7853 add.emplace_back(hi, y2);
7854 if (hi < B.x())
7855 add.emplace_back(hi, y);
7856 } else {
7857 if (hi < A.x())
7858 add.emplace_back(hi, y);
7859 add.emplace_back(hi, y2);
7860 add.emplace_back(lo, y2);
7861 if (lo > B.x())
7862 add.emplace_back(lo, y);
7863 }
7864 } else {
7865 long long x = e.fixed, x2 = x + step_x * depth;
7866 if (A.y() < B.y()) {
7867 if (lo > A.y())
7868 add.emplace_back(x, lo);
7869 add.emplace_back(x2, lo);
7870 add.emplace_back(x2, hi);
7871 if (hi < B.y())
7872 add.emplace_back(x, hi);
7873 } else {
7874 if (hi < A.y())
7875 add.emplace_back(x, hi);
7876 add.emplace_back(x2, hi);
7877 add.emplace_back(x2, lo);
7878 if (lo > B.y())
7879 add.emplace_back(x, lo);
7880 }
7881 }
7882 if (poly.size() > max_vertices or add.size() > max_vertices - poly.size())
7883 return false;
7884 if (!ortho_bump_valid(poly, A, B, add, edge_i, inward))
7885 return false;
7886
7887 poly.insert(poly.begin() + edge_i + 1, add.begin(), add.end());
7888 return true;
7889}
7890
7891// Picks edge i with probability proportional to
7892// e.len * (4 + min(global_timestamp - last_used[i], 8)).
7893// O(|poly|).
7894inline int ortho_pick_poly_edge(const std::vector<point<long long>> &poly,
7895 std::vector<int> &last_used, int &time_stamp) {
7896 int m = static_cast<int>(poly.size());
7897 if (last_used.size() != static_cast<size_t>(m)) {
7898 last_used.assign(m, 0);
7899 time_stamp = 0;
7900 }
7901 std::vector<long long> weights(m);
7902 long long total = 0;
7903 for (int i = 0; i < m; ++i) {
7904 ortho_poly_edge e = ortho_analyze_edge(poly, i);
7905 weights[i] = e.len * (4 + std::min(time_stamp - last_used[i], 8));
7906 total += weights[i];
7907 }
7908 long long pick = next<long long>(0, total - 1);
7909 for (int i = 0; i < m; ++i) {
7910 pick -= weights[i];
7911 if (pick < 0) {
7912 last_used[i] = ++time_stamp;
7913 return i;
7914 }
7915 }
7916 last_used[m - 1] = ++time_stamp;
7917 return m - 1;
7918}
7919
7920// One random inflate/cut attempt.
7921// O(|poly|).
7922inline bool
7923ortho_try_bump(std::vector<point<long long>> &poly, int n,
7924 std::vector<int> &last_used, int &time_stamp,
7925 bool outward_only = false,
7926 size_t max_vertices = std::numeric_limits<size_t>::max()) {
7927 if (poly.size() < 3)
7928 return false;
7929
7930 int ei = ortho_pick_poly_edge(poly, last_used, time_stamp);
7931 ortho_poly_edge e = ortho_analyze_edge(poly, ei);
7932
7933 // Edge subdivision can leave length-1 segments; a tab needs span >= 2.
7934 if (e.len < 2)
7935 return false;
7936
7937 // Random subinterval [lo, lo + span] on the edge, with 2 <= span <= e.len.
7938 long long span = next<long long>(2, e.len);
7939 long long lo = next<long long>(e.lo, e.hi - span);
7940
7941 // max_depth: cap on perpendicular tab/notch height (~sqrt(n), in [2, 12]).
7942 // depth: actual height; shallow usually, up to max_depth 10% of the time.
7943 long long max_depth =
7944 std::clamp(static_cast<long long>(std::sqrt(n) / 2 + 2), 2LL, 12LL);
7945 long long depth =
7946 next(10) == 0 ? next<long long>(std::max(2LL, max_depth / 2), max_depth)
7947 : next<long long>(1, std::max(2LL, max_depth / 3));
7948
7949 bool inward = !outward_only and next(4) == 0;
7950 return ortho_bump_edge(poly, ei, e, lo, lo + span, depth, inward,
7951 max_vertices);
7952}
7953
7954// Drops axis-aligned collinear vertices.
7955// O(n).
7956inline std::vector<point<long long>>
7957ortho_simplify_collinear(std::vector<point<long long>> poly) {
7958 int n = static_cast<int>(poly.size());
7959 if (n < 3)
7960 return poly;
7961 std::vector<point<long long>> out;
7962 out.reserve(n);
7963 for (int i = 0; i < n; ++i) {
7964 if (!ortho_axis_collinear(poly[(i + n - 1) % n], poly[i],
7965 poly[(i + 1) % n]))
7966 out.push_back(poly[i]);
7967 }
7968 return out.size() >= 3 ? out : poly;
7969}
7970
7971// Removes one collinear vertex.
7972// O(n).
7973inline bool ortho_remove_one_collinear(std::vector<point<long long>> &poly) {
7974 int n = static_cast<int>(poly.size());
7975 if (n < 4)
7976 return false;
7977 for (int i = 0; i < n; ++i) {
7978 if (!ortho_axis_collinear(poly[(i + n - 1) % n], poly[i],
7979 poly[(i + 1) % n]))
7980 continue;
7981 poly.erase(poly.begin() + i);
7982 return true;
7983 }
7984 return false;
7985}
7986
7987// Inserts collinear vertices on straight edges until size reaches `target` (or
7988// no edge has spare integer points). Preserves boundary order.
7989// O(target).
7990inline void ortho_fill_collinear(std::vector<point<long long>> &poly,
7991 int target) {
7992 int need = target - static_cast<int>(poly.size());
7993 if (need <= 0)
7994 return;
7995
7996 std::vector<point<long long>> out;
7997 int m = static_cast<int>(poly.size());
7998 out.reserve(poly.size() + need);
7999
8000 for (int i = 0; i < m; ++i) {
8001 point<long long> a = poly[i], b = poly[(i + 1) % m];
8002 out.push_back(a);
8003 if (need <= 0)
8004 continue;
8005
8006 ortho_poly_edge e = ortho_analyze_edge(poly, i);
8007 long long cap = e.len - 1;
8008 if (cap <= 0)
8009 continue;
8010
8011 // Adds `take` collinear vertices to the boundary.
8012 long long take = std::min<long long>(need, cap);
8013 bool forward = e.horiz ? a.x() < b.x() : a.y() < b.y();
8014 for (long long k = 0; k < take; ++k) {
8015 long long off = (k + 1) * (cap + 1) / (take + 1);
8016 long long coord = forward ? e.lo + off : e.hi - off;
8017 if (e.horiz)
8018 out.push_back({coord, e.fixed});
8019 else
8020 out.push_back({e.fixed, coord});
8021 }
8022 need -= static_cast<int>(take);
8023 }
8024 poly.swap(out);
8025}
8026
8027// Inserts outward depth-1 corrugation tabs on straight edges until size reaches
8028// `target` (or no edge has room for another tab). Preserves boundary order.
8029// Assumes the scale-up step left every edge on a grid with spacing >= 4.
8030// Each tab perturbs a coordinate by 1 and keeps a >= 2 margin from both
8031// corners, so tabs can only meet tabs on the same or a directly facing edge.
8032// The result is therefore simple and free of collinear triples by construction.
8033// O(target).
8034inline void ortho_fill_corrugation(std::vector<point<long long>> &poly,
8035 size_t target) {
8036 size_t n_sz = poly.size();
8037 if (n_sz >= target)
8038 return;
8039
8040 size_t extra_left = target - n_sz;
8041
8042 std::vector<point<long long>> out;
8043 out.reserve(target);
8044 int n = static_cast<int>(poly.size());
8045
8046 for (int i = 0; i < n; ++i) {
8047 point<long long> a = poly[i], b = poly[(i + 1) % n];
8048 out.push_back(a);
8049
8050 if (extra_left < 4)
8051 continue;
8052
8053 ortho_poly_edge e = ortho_analyze_edge(poly, i);
8054 if (e.len < 5)
8055 continue;
8056
8057 long long dir = (e.horiz ? a.x() < b.x() : a.y() < b.y()) ? 1 : -1;
8058 long long start = e.horiz ? a.x() : a.y();
8059 long long end = e.horiz ? b.x() : b.y();
8060
8061 for (long long pos = start + 2 * dir;
8062 extra_left >= 4 and (pos - end) * dir <= -3; pos += 2 * dir) {
8063 if (e.horiz) {
8064 long long y2 = e.fixed + e.out_y;
8065 out.push_back({pos, e.fixed});
8066 out.push_back({pos, y2});
8067 out.push_back({pos + dir, y2});
8068 out.push_back({pos + dir, e.fixed});
8069 } else {
8070 long long x2 = e.fixed + e.out_x;
8071 out.push_back({e.fixed, pos});
8072 out.push_back({x2, pos});
8073 out.push_back({x2, pos + dir});
8074 out.push_back({e.fixed, pos + dir});
8075 }
8076 extra_left -= 4;
8077 }
8078 }
8079
8080 poly.swap(out);
8081}
8082
8083// CCW square seed plus boundary inflate/cut to about n vertices.
8084// O(n^2) for n <= 1000; O(n) otherwise.
8085inline std::vector<point<long long>> build_orthogonal_polygon(int n,
8086 bool strict) {
8087 bool scale_up = n > 1000;
8088
8089 long long side = std::max(3LL, static_cast<long long>(std::sqrt(n)));
8090 if (scale_up)
8091 side = std::clamp(static_cast<long long>(2 * std::sqrt(std::sqrt(n))),
8092 8LL, 64LL);
8093 std::vector<point<long long>> poly = {
8094 {0, 0}, {side, 0}, {side, side}, {0, side}};
8095
8096 int target_ops = scale_up ? std::max(1, static_cast<int>(4 * side - 4) / 2)
8097 : std::max(1, (n - 4) / 2);
8098
8099 if (scale_up)
8100 target_ops = std::min(
8101 target_ops,
8102 400 + static_cast<int>(4 * std::sqrt(static_cast<double>(side))));
8103
8104 int failure_limit = std::min(target_ops * 8, 2000);
8105
8106 std::vector<int> last_used;
8107 int time_stamp = 0, consecutive_failures = 0;
8108 size_t max_vertices =
8109 scale_up ? std::numeric_limits<size_t>::max() : static_cast<size_t>(n);
8110 for (int ops = 0; ops < target_ops;) {
8111 if (!scale_up and poly.size() + 2 > static_cast<size_t>(n))
8112 break;
8113
8114 if (ortho_try_bump(poly, n, last_used, time_stamp, scale_up,
8115 max_vertices)) {
8116 ++ops;
8117 consecutive_failures = 0;
8118 } else if (++consecutive_failures >= failure_limit) {
8119 break;
8120 }
8121 }
8122 if (strict)
8123 poly = ortho_simplify_collinear(std::move(poly));
8124
8125 if (scale_up) {
8126 while (poly.size() > static_cast<size_t>(n) and
8127 ortho_remove_one_collinear(poly))
8128 ;
8129 long long upscale = std::max(
8130 4LL, ((static_cast<long long>(n) + 3) / 4 + side - 1) / side);
8131 for (point<long long> &p : poly)
8132 p = {p.x() * upscale, p.y() * upscale};
8133 if (strict)
8134 ortho_fill_corrugation(poly, n);
8135 else
8136 ortho_fill_collinear(poly, n);
8137 } else if (!strict)
8138 ortho_fill_collinear(poly, n);
8139
8140 return poly;
8141}
8142
8143} // namespace detail
8144
8145// Random simple polygon.
8146// If strict, vertex set has no three collinear points
8147// (random_points_general_position); otherwise samples distinct grid points
8148// (collinear triples allowed), so it might be the case that (polygon[i],
8149// polygon[i+1], and polygon[i+2]) are collinear. Polygonizes via
8150// random_simple_polygon_through_points. Always counterclockwise.
8151// O(n log n) expected.
8152inline std::vector<point<long long>>
8153random_simple_polygon(int n, long long min_coord, long long max_coord,
8154 bool strict = false) {
8155 tgen_ensure(n >= 3,
8156 "geometry: random_simple_polygon: n must be at least 3");
8157 tgen_ensure(max_coord >= min_coord,
8158 "geometry: random_simple_polygon: min_coord must be at most "
8159 "max_coord");
8160 tgen_ensure(static_cast<detail::i128>(max_coord) - min_coord <=
8161 std::numeric_limits<long long>::max(),
8162 "geometry: random_simple_polygon: coordinate range too large");
8163
8164 std::vector<point<long long>> points =
8165 strict ? random_points_general_position(n, min_coord, max_coord)
8166 : detail::random_distinct_points_in_box(n, min_coord, max_coord);
8167 return random_simple_polygon_through_points(points);
8168}
8169
8170// Random orthogonal simple polygon, CCW. Each local bump/scale/fill step
8171// preserves full simplicity, so the result is valid by construction.
8172// Exactly n vertices when !strict; at most n when strict (near n for n > 1000).
8173// O(n^2) for n <= 1000; O(n) otherwise.
8174inline std::vector<point<long long>>
8175random_orthogonal_polygon(int n, long long min_coord, long long max_coord,
8176 bool strict = false) {
8177 tgen_ensure(n >= 4,
8178 "geometry: random_orthogonal_polygon: n must be at least 4");
8179 tgen_ensure(max_coord >= min_coord,
8180 "geometry: random_orthogonal_polygon: min_coord must be at "
8181 "most max_coord");
8182 tgen_ensure(static_cast<detail::i128>(max_coord) - min_coord + 1 <=
8183 std::numeric_limits<long long>::max(),
8184 "geometry: random_orthogonal_polygon: coordinate range too "
8185 "large");
8186 long long width = max_coord - min_coord + 1;
8187 tgen_ensure(width >= 4,
8188 "geometry: random_orthogonal_polygon: coordinate range too "
8189 "small");
8190
8191 long long min_side = std::max(3LL, static_cast<long long>(std::sqrt(n)));
8192 if (n > 1000)
8193 min_side =
8194 std::max<long long>(min_side, (static_cast<long long>(n) + 3) / 4);
8195 tgen_ensure(min_side < width,
8196 "geometry: random_orthogonal_polygon: coordinate range too "
8197 "small");
8198
8199 for (int attempt = 0; attempt < 8; ++attempt) {
8200 std::vector<point<long long>> poly =
8201 detail::build_orthogonal_polygon(n, strict);
8202
8203 if (!strict and poly.size() != static_cast<size_t>(n))
8204 continue;
8205
8206 detail::i128 min_x = poly[0].x(), max_x = poly[0].x();
8207 detail::i128 min_y = poly[0].y(), max_y = poly[0].y();
8208 for (point<long long> p : poly) {
8209 min_x = std::min(min_x, detail::i128(p.x()));
8210 max_x = std::max(max_x, detail::i128(p.x()));
8211 min_y = std::min(min_y, detail::i128(p.y()));
8212 max_y = std::max(max_y, detail::i128(p.y()));
8213 }
8214 if (max_x - min_x >= width or max_y - min_y >= width)
8215 continue;
8216
8217 detail::place_inside_box(poly, min_coord, max_coord);
8218 detail::randomize_cyclic_shift(poly);
8219 return poly;
8220 }
8221
8222 throw tgen::detail::error(
8223 "geometry: random_orthogonal_polygon: generation failed");
8224}
8225
8226} // namespace geometry
8227
8228/************
8229 * *
8230 * HACK *
8231 * *
8232 ************/
8233
8234namespace hack {
8235
8236namespace detail {
8237
8238using namespace tgen::detail;
8239
8240// Computes polynomial hash of a string.
8241// O(|s|).
8242inline int hash_string(const std::string &s, int base, int mod) {
8243 long long h = 0;
8244 for (char c : s)
8245 h = (h * base + c - 'a' + 1) % mod;
8246 return static_cast<int>(h);
8247}
8248
8249// Estimates the length of the string to very likely have a collision.
8250inline int estimate_length(int alphabet_size, int mod) {
8251 // Magic constants.
8252 double base_len = 2.5 * std::log(std::sqrt(mod));
8253 double scale = std::log(alphabet_size) / std::log(2.0);
8254 double adjusted = base_len / std::max(1.0, scale * 0.7);
8255
8256 // More candidates than hashes guarantees that a collision exists.
8257 // Use long long for overflow safety: each product is at most mod *
8258 // alphabet_size, and both parameters are int.
8259 int min_length = 0;
8260 for (long long ways = 1; ways <= mod; ways *= alphabet_size)
8261 ++min_length;
8262 return std::max(min_length, static_cast<int>(std::ceil(adjusted)));
8263}
8264
8265// Collides two strings to have the same polynomial hash.
8266// O(sqrt(mod) log(mod)) with high probability.
8267inline std::pair<std::string, std::string>
8268birthday_attack(const std::vector<std::string> &alphabet, int base, int mod) {
8269 tgen_ensure(0 < base and base < mod,
8270 "birthday_attack: base must be in (0, mod)");
8271 std::map<uint64_t, std::vector<int>> seen;
8272 int length = estimate_length(static_cast<int>(alphabet.size()), mod);
8273
8274 while (true) {
8275 std::vector<int> seq(length);
8276
8277 std::string s;
8278
8279 for (int i = 0; i < length; ++i) {
8280 seq[i] = next<int>(0, static_cast<int>(alphabet.size()) - 1);
8281 s += alphabet[seq[i]];
8282 }
8283
8284 int h = hash_string(s, base, mod);
8285
8286 auto it = seen.find(h);
8287 if (it != seen.end() and it->second != seq) {
8288 std::string a, b;
8289
8290 for (int x : it->second)
8291 a += alphabet[x];
8292 for (int x : seq)
8293 b += alphabet[x];
8294
8295 if (a != b)
8296 return {a, b};
8297 }
8298
8299 seen[h] = seq;
8300 }
8301}
8302
8303// Tried to find correct multipliers for unordered_map/set to force
8304// collisions. O(1).
8305inline std::set<long long> std_hash_multipliers() {
8306 std::set<long long> multipliers = {85229};
8307
8308 // Codeforces GCC GNU G++17 7.3.0 case.
8309 bool codeforces_gcc_case = true;
8310 if (cpp.version_ != 0 and cpp.version_ != 17)
8311 codeforces_gcc_case = false;
8312 if (compiler.kind_ != compiler_kind::unknown and
8313 compiler.kind_ != compiler_kind::gcc)
8314 codeforces_gcc_case = false;
8315 if (compiler.major_ > 7)
8316 codeforces_gcc_case = false;
8317
8318 if (codeforces_gcc_case)
8319 multipliers.insert(107897);
8320
8321 return multipliers;
8322}
8323
8324} // namespace detail
8325
8326// Fetches prefix of length n of the string "abacabadabacabae...".
8327// O(n).
8328inline std::string abacaba(int n) {
8329 tgen_ensure(n > 0, "str: size must be positive");
8330 std::string str = "a";
8331 char c = 'a';
8332 while (static_cast<int>(str.size()) < n) {
8333 int prev_size = static_cast<int>(str.size());
8334 str += ++c;
8335 for (int j = 0; j < prev_size and static_cast<int>(str.size()) < n; ++j)
8336 str += str[j];
8337 }
8338 return str;
8339}
8340
8341// Two strings that have same polynomial hash for any base, for
8342// mod = power of 2 up to 2^64.
8343// Thue–Morse.
8344// O(1).
8345inline std::pair<std::string, std::string> unsigned_polynomial_hash() {
8346 std::string a, b;
8347 int size = 1 << 10;
8348 for (int i = 0; i < size; ++i) {
8349 a += static_cast<char>('a' + math::detail::popcount(i) % 2);
8350 b += static_cast<char>('a' + ('b' - a[i]));
8351 }
8352 return {a, b};
8353}
8354
8355// Collides two strings to have the same polynomial hash.
8356// O(sqrt(mod) log(mod)) with high probability.
8357// 0 < base < mod.
8358inline std::pair<std::string, std::string> polynomial_hash(int alphabet_size,
8359 int base, int mod) {
8360 tgen_ensure(alphabet_size > 1,
8361 "hack: polynomial_hash: alphabet size must be greater "
8362 "than 1");
8363 tgen_ensure(0 < base and base < mod,
8364 "hack: polynomial_hash: base must be in (0, mod)");
8365
8366 std::vector<std::string> alphabet(alphabet_size);
8367 for (int i = 0; i < alphabet_size; ++i)
8368 alphabet[i] = std::string(1, static_cast<char>('a' + i));
8369 std::iota(alphabet.begin(), alphabet.end(), 'a');
8370 return detail::birthday_attack(alphabet, base, mod);
8371}
8372
8373// Collides two strings to have the same polynomial hash for multiple bases
8374// and mods (up to 2 pairs).
8375// O(sqrt(mod) log^2 (mod)) with high probability,
8376// with mod = max(mod_1, mod_2).
8377inline std::pair<std::string, std::string>
8378polynomial_hash(int alphabet_size, std::vector<int> bases,
8379 std::vector<int> mods) {
8380 tgen_ensure(alphabet_size > 1,
8381 "hack: polynomial_hash: alphabet size must be greater "
8382 "than 1");
8383 tgen_ensure(bases.size() == mods.size(),
8384 "hack: polynomial_hash: bases and mods must have the same "
8385 "size");
8386 tgen_ensure(bases.size() > 0,
8387 "hack: polynomial_hash: must have at least one (base, mod) "
8388 "pair");
8389 tgen_ensure(bases.size() <= 2,
8390 "hack: polynomial_hash: multi-hash hack only supported "
8391 "for up to 2 (base, mod) pairs");
8392
8393 std::vector<std::string> alphabet(alphabet_size);
8394 for (int i = 0; i < alphabet_size; ++i)
8395 alphabet[i] = std::string(1, static_cast<char>('a' + i));
8396 auto [S1, T1] = detail::birthday_attack(alphabet, bases[0], mods[0]);
8397 if (bases.size() == 1)
8398 return {S1, T1};
8399 return detail::birthday_attack({S1, T1}, bases[1], mods[1]);
8400}
8401
8402// Returns a list of integers for unordered_map/set to force collisions.
8403// O(size).
8404inline std::vector<long long> std_unordered(int size) {
8405 tgen_ensure(size > 0, "hack: std_unordered: size must be positive");
8406 std::set<long long> multipliers = detail::std_hash_multipliers();
8407 long long mult = 1;
8408 std::set<long long>::iterator it = multipliers.begin();
8409
8410 std::vector<long long> list;
8411 while (static_cast<int>(list.size()) < size) {
8412 list.push_back(mult * (*it));
8413 ++it;
8414 if (it == multipliers.end()) {
8415 it = multipliers.begin();
8416 ++mult;
8417 }
8418 }
8419 return list;
8420}
8421
8422// Returns queries that force \Theta(q sqrt n) asymptotic
8423// for Mo algorithm for offline range queries.
8424// Forces \Theta(q sqrt n) pointer moves for any ordering.
8425// O(n log n + q).
8426inline std::vector<std::pair<int, int>> mo_worst_case(int n, int q) {
8427 std::set<std::pair<int, int>> queries;
8428
8429 // Adversarial case.
8430 int sq = static_cast<int>(std::sqrt(n));
8431 for (int i = 0; i < sq; ++i) {
8432 for (int j = i; j < sq; ++j) {
8433 if (i * sq < n and j * sq < n)
8434 queries.emplace(i * sq, j * sq);
8435 }
8436 }
8437
8438 // Push extra queries.
8439 for (int i = 0; i < n; ++i)
8440 if (queries.size() < size_t(q)) {
8441 queries.emplace(0, i);
8442 queries.emplace(i, i);
8443 queries.emplace(i, n - 1);
8444 }
8445
8446 std::vector<std::pair<int, int>> pool(queries.begin(), queries.end());
8447 while (pool.size() < size_t(q)) {
8448 int l = next(0, n - 1);
8449 pool.emplace_back(l, next(l, n - 1));
8450 }
8451
8452 return choose(shuffled(pool), q);
8453}
8454
8455// Returns list of strings that have a high cost to insert in a std::set.
8456// Forces cost \Theta(size log(size)).
8457// Generates: {b, ab, aab, aaab, ...}.
8458// O(size log(size)).
8460 std::vector<std::string> list;
8461 int k = 0, left = size;
8462 while (left > 0) {
8463 int cur_size = std::min(left, k + 1);
8464 left -= cur_size;
8465
8466 char right_char = cur_size == k + 1 ? 'b' : 'c';
8467 list.push_back(std::string(cur_size - 1, 'a') + right_char);
8468
8469 ++k;
8470 }
8471 return tgen::shuffled(list);
8472}
8473
8474// Graph for Dijkstra implementations that relax with <= instead of <.
8475// Unit-weight layered graph: 0 -> {1,2}, then disjoint
8476// 2x2 gadgets (i,i+1) -> {i+2,i+3} for i = 1,3,5,... Many vertices share the
8477// same dist from 0; with `d + w <= dist[j]` each pop re-relaxes the whole
8478// frontier below it. m = 2(n - 2) edges.
8479// O(n).
8482 n >= 3,
8483 "hack: non_strict_relaxation_dijkstra_bug: needs at least 3 vertices");
8484
8485 egraph<int>::value g(n, {}, true);
8486 g.edge_weighted();
8487 g.add_edge(0, 1, 1);
8488 g.add_edge(0, 2, 1);
8489 for (int i = 1; i + 2 < n; i += 2) {
8490 g.add_edge(i, i + 2, 1);
8491 if (i + 3 < n)
8492 g.add_edge(i, i + 3, 1);
8493
8494 g.add_edge(i + 1, i + 2, 1);
8495 if (i + 3 < n)
8496 g.add_edge(i + 1, i + 3, 1);
8497 }
8498
8499 return g.shuffle_except({0});
8500}
8501
8502// Graph for Dijkstra implementations that do not skip stale heap entries
8503// (`if (d > dist[i]) continue`).
8504// Hub mid = n/2: star 0 -> 1..mid-1 (weights 1..mid-1), funnel i -> mid
8505// (weights 1,3,5,...), then mid -> mid+1.. (weight 1).
8506// Without a stale-heap check, mid and its in-neighbors are re-popped and
8507// re-relax.
8508// m = n + mid - 3 edges, mid = floor(n/2).
8509// O(n).
8511 tgen_ensure(n >= 4,
8512 "hack: stale_heap_dijkstra_bug: needs at least 4 vertices");
8513
8514 int mid = n / 2;
8515 egraph<int>::value g(n, {}, true);
8516 g.edge_weighted();
8517 for (int i = 1; i < mid; ++i)
8518 g.add_edge(0, i, i);
8519 for (int i = 1; i < mid; ++i)
8520 g.add_edge(i, mid, 2 * (mid - i) - 1);
8521 for (int i = mid + 1; i < n; ++i)
8522 g.add_edge(mid, i, 1);
8523
8524 return g.shuffle_except({0});
8525}
8526
8527// Worst-case for FIFO-SPFA from vertex 0: Theta(n^2) edge scans.
8528// Upper chain ai -> a(i+1) has weight 1. Each ai -> b0 has weight
8529// 2(k-i), so successive upper vertices improve the entire zero-weight lower
8530// chain. FIFO scheduling propagates these improvements in separate waves.
8531// n = 2k, m = 3k - 2. O(n) construction.
8532inline egraph<int>::value spfa(int n) {
8533 tgen_ensure(n >= 2, "hack: spfa: n must be at least 2");
8534 tgen_ensure(n % 2 == 0, "hack: spfa: n must be even");
8535 egraph<int>::value g(n, {}, true);
8536 g.edge_weighted();
8537 const int k = n / 2;
8538 for (int i = 0; i + 1 < k; ++i) {
8539 g.add_edge(i, i + 1, 1);
8540 g.add_edge(k + i, k + i + 1, 0);
8541 }
8542 for (int i = 0; i < k; ++i)
8543 g.add_edge(i, k, 2 * (k - i));
8544 return g.shuffle_except({0});
8545}
8546
8547// Zadeh (1972) anti-shortest-paths flow network for Edmonds-Karp and Dinitz.
8548// Source is vertex 0; sink is vertex 4l + 2k + 1.
8549// n = 4l + 2k + 2, m = 6l + 4k + k^2 - 4.
8550// O(l + k^2).
8551inline egraph<int>::value dinitz_worst_case(int k, int l) {
8552 tgen_ensure(k >= 1, "hack: dinitz_worst_case: k must be at least 1");
8553 tgen_ensure(l >= 1, "hack: dinitz_worst_case: l must be at least 1");
8554
8555 // Validate in wide arithmetic before computing int indices and capacities.
8556 const detail::i128 capacity = detail::i128(k) * k * l;
8557 const long long vertices = 4LL * l + 2LL * k + 2;
8558 const long long edges = 6LL * l + 4LL * k + 1LL * k * k - 4;
8559 tgen_ensure(capacity <= std::numeric_limits<int>::max() and
8560 vertices <= std::numeric_limits<int>::max() and
8561 edges <= std::numeric_limits<int>::max(),
8562 "hack: dinitz_worst_case: size or capacity too large");
8563
8564 const int p1 = 2 * l - 1;
8565 const int p2 = 2 * l;
8566 const int q1 = 2 * l + 1;
8567 const int q2 = 2 * l + 2;
8568 const int n = 4 * l + 2 * k + 2;
8569
8570 const int flow_cap = k * k * l;
8571 const int layer_cap = k * k;
8572
8573 auto a = [&](int i) { return 2 * l + 3 + 2 * i; };
8574 auto b = [&](int i) { return 2 * l + 4 + 2 * i; };
8575 auto t = [&](int i) { return 4 * l + 2 * k + 1 - i; };
8576
8577 egraph<int>::value g(n, {}, true);
8578 g.edge_weighted();
8579
8580 for (int i = 0; i + 1 < 2 * l - 1; ++i)
8581 g.add_edge(i, i + 1, flow_cap);
8582 for (int i = 0; i + 1 < 2 * l - 1; ++i)
8583 g.add_edge(t(i + 1), t(i), flow_cap);
8584
8585 for (int i = 0; i < 2 * l - 1; i += 2) {
8586 g.add_edge(i, i % 4 == 0 ? p1 : p2, layer_cap);
8587 g.add_edge(i % 4 == 0 ? q1 : q2, t(i), layer_cap);
8588 }
8589
8590 for (int i = 0; i < k; ++i) {
8591 g.add_edge(p1, a(i), flow_cap);
8592 g.add_edge(p2, b(i), flow_cap);
8593 g.add_edge(a(i), q2, flow_cap);
8594 g.add_edge(b(i), q1, flow_cap);
8595 }
8596
8597 for (int i = 0; i < k; ++i)
8598 for (int j = 0; j < k; ++j)
8599 g.add_edge(a(i), b(j), 1);
8600
8601 return g;
8602}
8603
8604// Returns a mask of length 19938, with weights such that xor-ing with mt19937
8605// outputs yields 0.
8606// O(1).
8607template <typename T> std::vector<bool> mt19937_xor_hash() {
8608 static_assert(std::is_same_v<T, int> or std::is_same_v<T, long long>,
8609 "hack: mt19937_xor_hash: T must be int or long long");
8610
8611 constexpr std::size_t deg = 19937;
8612
8613 std::bitset<deg + 1> a, b, c;
8614 b[deg] = c[deg] = 1;
8615 std::size_t l = 0, shift = 1;
8616 std::mt19937 rng32;
8617 std::mt19937_64 rng64;
8618 for (std::size_t n = 0; n < deg * 2; ++n) {
8619 a >>= 1;
8620 if constexpr (std::is_same_v<T, int>)
8621 a[deg] = rng32() & 1;
8622 else
8623 a[deg] = rng64() & 1;
8624
8625 if ((c & a).count() % 2 == 0) {
8626 ++shift;
8627 continue;
8628 }
8629
8630 std::bitset<deg + 1> oc = c;
8631 c ^= (b >> shift);
8632 if (2 * l <= n) {
8633 l = n + 1 - l;
8634 b = oc;
8635 shift = 1;
8636 } else {
8637 ++shift;
8638 }
8639 }
8640
8641 std::vector<bool> mask(deg + 1);
8642 for (std::size_t i = 0; i <= deg; ++i)
8643 mask[i] = c[i];
8644 return mask;
8645}
8646
8647// Convex polygon that breaks naive rotating calipers for maximum vertex
8648// distance (advances j while dist(i, next(j)) > dist(i, j) instead of using
8649// ccw).
8650// O(1).
8651inline std::vector<geometry::point<double>>
8653 return {
8654 {-0.9846, -1.53251}, {0.49946, 1.19525}, {0.79916, 0.98291},
8655 {4.02136, -1.57843}, {3.92734, -2.37856}, {3.88558, -2.37188},
8656 };
8657}
8658
8659namespace detail {
8660
8661// Builds a hack block of order k (length fib(2k+1)).
8662// O(fib(2k+1)).
8663inline std::vector<int> segment_tree_beats_worst_case_block(int k) {
8664 tgen_ensure(k >= 1,
8665 "hack: segment_tree_beats_worst_case: k must be at least 1");
8666
8667 std::vector<int> a(k + 1), b(k + 1);
8668 std::vector<std::vector<int>> vf(k + 1), vg(k + 1);
8669
8670 a[1] = b[1] = 1;
8671 vf[1] = {1};
8672 vg[1] = {1, 0};
8673
8674 for (int i = 2; i <= k; ++i) {
8675 b[i] = b[i - 1] + a[i - 1];
8676 a[i] = b[i] + a[i - 1];
8677 for (int x : vf[i - 1])
8678 vf[i].push_back(x + a[i] + b[i]);
8679 vf[i].push_back(a[i]);
8680 for (int x : vg[i - 1])
8681 vf[i].push_back(x + a[i]);
8682 vg[i] = vf[i];
8683 vg[i].push_back(0);
8684 for (int x : vg[i - 1])
8685 vg[i].push_back(x);
8686 }
8687
8688 vf[k].push_back(0);
8689 return vf[k];
8690}
8691
8692// Appends one update round for the tiled array (offset (round * an) mod L).
8693// O(fib(2k+1)).
8694inline void
8695segment_tree_beats_append_round(std::vector<std::vector<int>> &updates,
8696 int block_len, int an, int bn, int n,
8697 int round) {
8698 const int off = (round * an) % block_len;
8699 const int add_off = (off + block_len - bn) % block_len;
8700 for (int k = 0; k < block_len; ++k) {
8701 const int s = k * block_len * block_len;
8702 const int sub_end = off + an;
8703 if (sub_end <= block_len)
8704 updates.push_back({1, s + off, s + sub_end, bn});
8705 else {
8706 updates.push_back({1, s + off, s + block_len, bn});
8707 updates.push_back({1, s, s + (sub_end - block_len), bn});
8708 }
8709 const int add_end = add_off + bn;
8710 if (add_end <= block_len)
8711 updates.push_back({0, s + add_off, s + add_end, an});
8712 else {
8713 updates.push_back({0, s + add_off, s + block_len, an});
8714 updates.push_back({0, s, s + (add_end - block_len), an});
8715 }
8716 }
8717 updates.push_back({2, 0, n, an});
8718 for (int k = 0; k < block_len; ++k) {
8719 const int s = k * block_len * block_len;
8720 updates.push_back({3, s + (off + an - 1) % block_len, 0});
8721 }
8722}
8723
8724} // namespace detail
8725
8726// Array and updates for worst case of segment tree beats.
8727// O(fib(2k+1)^3 + q).
8728inline std::pair<std::vector<int>, std::vector<std::vector<int>>>
8729segment_tree_beats_worst_case(int k, int q) {
8730 tgen_ensure(k >= 1,
8731 "hack: segment_tree_beats_worst_case: k must be at least 1");
8732 tgen_ensure(k <= 7, "hack: segment_tree_beats_worst_case: k too large");
8733 tgen_ensure(q > 0,
8734 "hack: segment_tree_beats_worst_case: q must be positive");
8735
8736 const auto &fib = math::fibonacci();
8737 const int block_len = static_cast<int>(fib[k * 2 + 1]);
8738 const int an = static_cast<int>(fib[k * 2]);
8739 const int bn = static_cast<int>(fib[k * 2 - 1]);
8740
8741 const int len = block_len;
8742 const int total = len * len * len;
8743
8744 std::vector<int> block = detail::segment_tree_beats_worst_case_block(k);
8745 std::vector<int> arr(total, 0);
8746 for (int x = 0; x < block_len; ++x) {
8747 const int s = x * len * len;
8748 for (int i = 0; i < block_len; ++i)
8749 arr[s + i] = block[i];
8750 }
8751
8752 std::vector<std::vector<int>> updates;
8753 updates.reserve(q);
8754 const int n = total;
8755 for (int round = 0; updates.size() < static_cast<std::size_t>(q); ++round) {
8756 detail::segment_tree_beats_append_round(updates, block_len, an, bn, n,
8757 round);
8758 if (updates.size() > static_cast<std::size_t>(q))
8759 updates.resize(q);
8760 }
8761 return {arr, updates};
8762}
8763
8764namespace detail {
8765
8766// Near-balanced binary tree in heap layout: parent i, children 2i+1 and 2i+2.
8767// Height Theta(log n).
8768// O(n).
8769inline tree::value binary_heap_tree(int n) {
8770 std::vector<std::pair<int, int>> edges;
8771 for (int i = 0; i < n; ++i) {
8772 if (2 * i + 1 < n)
8773 edges.emplace_back(i, 2 * i + 1);
8774 if (2 * i + 2 < n)
8775 edges.emplace_back(i, 2 * i + 2);
8776 }
8777 return tree::value(n, edges);
8778}
8779
8780// Appends leaves of the heap subtree rooted at `u` in left-to-right order.
8781// O(subtree size).
8782inline void heap_subtree_leaves(int n, int u, std::vector<int> &out) {
8783 if (2 * u + 1 >= n) {
8784 out.push_back(u);
8785 return;
8786 }
8787 heap_subtree_leaves(n, 2 * u + 1, out);
8788 if (2 * u + 2 < n)
8789 heap_subtree_leaves(n, 2 * u + 2, out);
8790}
8791
8792// Path queries between random leaves in the left and right subtrees of the
8793// root. On correct HLD or centroid decomposition each query visits
8794// Theta(log n) chains / centroid-tree nodes.
8795// O(n + q).
8796inline std::vector<std::pair<int, int>> tree_path_worst_queries(int n, int q) {
8797 std::vector<int> left, right;
8798 if (n > 1)
8799 heap_subtree_leaves(n, 1, left);
8800 if (n > 2)
8801 heap_subtree_leaves(n, 2, right);
8802
8803 std::vector<std::pair<int, int>> queries;
8804 for (int i = 0; i < q; ++i)
8805 queries.emplace_back(pick(left), pick(right));
8806 return queries;
8807}
8808
8809// Reverses the lowest `bits` bits of x.
8810// O(bits).
8811inline int reverse_bits(int x, int bits) {
8812 int r = 0;
8813 for (int i = 0; i < bits; ++i) {
8814 r = (r << 1) | (x & 1);
8815 x >>= 1;
8816 }
8817 return r;
8818}
8819
8820// Wilber bit-reversal leaf tour: maximizes left/right preferred-child
8821// alternations on a balanced tree, forcing Theta(q log n) preferred-path
8822// switches in link-cut trees.
8823// O(n log n + q).
8824inline std::vector<int> lct_worst_access(int n, int q) {
8825 int first_leaf = n / 2;
8826 int m = n - first_leaf;
8827
8828 int bits = 0;
8829 while ((1u << bits) < static_cast<unsigned>(m))
8830 ++bits;
8831
8832 std::vector<int> order;
8833 int span = 1 << bits;
8834 for (int i = 0; i < span; ++i) {
8835 int r = reverse_bits(i, bits);
8836 if (r < m)
8837 order.push_back(first_leaf + r);
8838 }
8839
8840 std::vector<int> access;
8841 for (int i = 0; i < q; ++i)
8842 access.push_back(order[i % m]);
8843 return access;
8844}
8845
8846} // namespace detail
8847
8848// Near-balanced tree plus path queries that force Theta(log n) centroid-tree
8849// nodes per query on correct centroid-decomposition implementations.
8850// O(n + q).
8851inline std::pair<tree::value, std::vector<std::pair<int, int>>>
8852centroid_decomposition_worst_case(int n, int q) {
8854 n >= 3,
8855 "hack: centroid_decomposition_worst_case: n must be at least 3");
8857 q >= 1,
8858 "hack: centroid_decomposition_worst_case: q must be at least 1");
8859
8860 return {detail::binary_heap_tree(n), detail::tree_path_worst_queries(n, q)};
8861}
8862
8863// Near-balanced tree plus path queries that force Theta(log n) heavy-light
8864// chains per query on correct heavy-light decomposition implementations.
8865// O(n + q).
8866inline std::pair<tree::value, std::vector<std::pair<int, int>>>
8867heavy_light_decomposition_worst_case(int n, int q) {
8869 n >= 3,
8870 "hack: heavy_light_decomposition_worst_case: n must be at least "
8871 "3");
8873 q >= 1,
8874 "hack: heavy_light_decomposition_worst_case: q must be at least 1");
8875
8876 return {detail::binary_heap_tree(n), detail::tree_path_worst_queries(n, q)};
8877}
8878
8879// Near-balanced tree plus a Wilber bit-reversal leaf-access sequence.
8880// O(n log n + q).
8881inline std::pair<tree::value, std::vector<int>>
8882link_cut_tree_worst_case(int n, int q) {
8883 tgen_ensure(n >= 2, "hack: link_cut_tree_worst_case: n must be at least 2");
8884 tgen_ensure(q >= 1, "hack: link_cut_tree_worst_case: q must be at least 1");
8885
8886 return {detail::binary_heap_tree(n), detail::lct_worst_access(n, q)};
8887}
8888
8889} // namespace hack
8890
8891/*********************
8892 * *
8893 * MISCELLANEOUS *
8894 * *
8895 *********************/
8896
8897namespace misc {
8898
8899// Generates a uniformly random balanced parentheses sequence with k '(' and k
8900// ')'. Valid means that for no prefix there are more ')' than '('.
8901// O(size).
8902inline std::string gen_parenthesis(int size) {
8903 tgen_ensure(size > 0 and size % 2 == 0,
8904 "misc: parenthesis: size must be a positive even number");
8905
8906 int k = size / 2;
8907 std::string s;
8908 int open = 0, close = 0;
8909
8910 for (int i = 0; i < size; ++i) {
8911 if (open == k) {
8912 s += ')';
8913 ++close;
8914 continue;
8915 }
8916 if (open == close) {
8917 s += '(';
8918 ++open;
8919 continue;
8920 }
8921
8922 long long a = k - open, b = k - close, h = open - close;
8923
8924 // Probability of placing '(':
8925 // P('(') = (k - open) * (h + 2) / ((k - open + k - close) * (h + 1))
8926 // Derived from ballot numbers ratio.
8927 long long num = a * (h + 2);
8928 long long den = (a + b) * (h + 1);
8929
8930 if (next<long long>(1, den) <= num) {
8931 s += '(';
8932 ++open;
8933 } else {
8934 s += ')';
8935 ++close;
8936 }
8937 }
8938
8939 return s;
8940}
8941
8942} // namespace misc
8943
8944} // namespace tgen
std::vector< int > many_by_distribution(int k, const std::vector< T > &distribution)
Returns many random indices with given probabilities.
Definition tgen.h:1040
auto shuffled(const C &container)
Shuffles a container.
Definition tgen.h:1069
C::value_type pick(const C &container)
Chooses a random element from container.
Definition tgen.h:1098
void shuffle(It first, It last)
Shuffles range inplace, for random_access_iterator.
Definition tgen.h:1059
T wnext(T left, T right, int w)
Returns a skewed random number in range.
Definition tgen.h:827
It::value_type pick(It first, It last)
Chooses a random element from an iterator range.
Definition tgen.h:1088
T next(T right)
Returns a random number smaller than value.
Definition tgen.h:703
size_t next_by_distribution(const std::vector< T > &distribution)
Returns random index with given probabilities.
Definition tgen.h:1028
C::value_type pick_by_distribution(const C &container, std::vector< T > distribution)
Chooses a random element with given probabilities.
Definition tgen.h:1108
#define tgen_ensure(cond,...)
Ensures condition is true.
Definition tgen.h:114
T next(T left, T right)
Returns a random number in range.
Definition tgen.h:724
T wnext(T right, int w)
Returns a skewed random number smaller than value.
Definition tgen.h:794
C choose(const C &container, int k)
Chooses elements from container, as in a subsequence fixed length.
Definition tgen.h:1136
std::vector< point< long long > > random_simple_polygon_through_points(const std::vector< point< long long > > &points)
Generates a random simple polygon through given points.
Definition tgen.h:7517
std::vector< point< long long > > random_points_general_position(int n, long long min_coord, long long max_coord)
Generates random points in general position inside a coordinate box.
Definition tgen.h:6998
std::vector< point< long long > > random_convex_polygon(int n, long long min_coord, long long max_coord, bool strict=false)
Generates a random convex polygon with given coordinate range.
Definition tgen.h:7449
std::vector< point< long long > > random_simple_polygon(int n, long long min_coord, long long max_coord, bool strict=false)
Generates a random simple polygon given coordinate range.
Definition tgen.h:8153
std::vector< point< long long > > random_orthogonal_polygon(int n, long long min_coord, long long max_coord, bool strict=false)
Generates a random orthogonal simple polygon.
Definition tgen.h:8175
wgraph< VWeight, int > vgraph
Vertex-weighted labeled graphs.
Definition tgen.h:6830
graph::value C(int n, bool is_directed=false)
Cycle graph.
Definition tgen.h:6868
wgraph< int, EWeight > egraph
Edge-weighted labeled graphs.
Definition tgen.h:6833
graph::value S(int n)
Star undirected graph.
Definition tgen.h:6892
graph::value K(int n1, int n2)
Complete bipartite undirected graph.
Definition tgen.h:6881
graph::value K(int n)
Complete undirected graph.
Definition tgen.h:6844
wgraph< int, int > graph
Unweighted labeled graphs.
Definition tgen.h:6836
graph::value P(int n, bool is_directed=false)
Path graph.
Definition tgen.h:6857
std::vector< std::pair< int, int > > mo_worst_case(int n, int q)
Query list that forces asymptotic worst-case for Mo's algorithm.
Definition tgen.h:8426
std::vector< bool > mt19937_xor_hash()
Mask that forces a zero XOR hash from std::mt19937 or std::mt19937_64.
Definition tgen.h:8607
egraph< int >::value spfa(int n)
Worst-case for FIFO-SPFA.
Definition tgen.h:8532
egraph< int >::value non_strict_relaxation_dijkstra_bug(int n)
Directed weighted graph for Dijkstra with non-strict relaxation.
Definition tgen.h:8480
std::string abacaba(int n)
Returns the prefix of the infinite word "abacabad...".
Definition tgen.h:8328
std::vector< geometry::point< double > > naive_rotating_calipers_max_dist_bug()
Convex polygon that breaks naive rotating calipers for maximum distance.
Definition tgen.h:8652
std::vector< long long > std_unordered(int size)
List of integers that tries to force collision on std::unordered_set.
Definition tgen.h:8404
std::vector< std::string > string_set_worst_case(int size)
List of strings that have high cost to insert in a std::set.
Definition tgen.h:8459
std::pair< std::string, std::string > unsigned_polynomial_hash()
Returns two strings that force polynomial hash collision for power-of-two mod.
Definition tgen.h:8345
std::pair< std::string, std::string > polynomial_hash(int alphabet_size, int base, int mod)
Returns two strings that force polynomial hash collision given base and mod.
Definition tgen.h:8358
egraph< int >::value dinitz_worst_case(int k, int l)
Flow network for Edmonds-Karp and Dinitz worst-case.
Definition tgen.h:8551
egraph< int >::value stale_heap_dijkstra_bug(int n)
Directed weighted graph for Dijkstra without a stale-heap check.
Definition tgen.h:8510
uint64_t prime_from(uint64_t left)
Computes smallest prime from given value.
Definition tgen.h:3133
uint64_t gen_divisor_count(uint64_t left, uint64_t right, int divisor_count)
Generates random number in range with a given prime number of divisors.
Definition tgen.h:3162
std::vector< int > gen_partition_fixed_size(int n, int k, int part_left=0, std::optional< int > part_right=std::nullopt)
Generates a random partition with fixed size of a number.
Definition tgen.h:3434
uint64_t totient(uint64_t n)
Euler's totient function.
Definition tgen.h:2990
uint64_t congruent_from(uint64_t left, std::vector< uint64_t > rems, std::vector< uint64_t > mods)
Computes smallest congruent from given value.
Definition tgen.h:3237
uint64_t congruent_upto(uint64_t right, uint64_t rem, uint64_t mod)
Computes largest congruent up to given value.
Definition tgen.h:3331
uint64_t gen_prime(uint64_t left, uint64_t right)
Generates a random prime in given range.
Definition tgen.h:3105
std::vector< uint64_t > factor(uint64_t n)
Factors a number into primes.
Definition tgen.h:2959
int num_divisors(uint64_t n)
Computes the number of divisors of a given number.
Definition tgen.h:3152
bool is_prime(uint64_t n)
Checks if a number is prime.
Definition tgen.h:2707
std::vector< int > gen_partition(int n, int part_left=1, std::optional< int > part_right=std::nullopt)
Generates a random partition of a number.
Definition tgen.h:3356
constexpr int FFT_MOD
FFT/NTT mod.
Definition tgen.h:3337
uint64_t gen_congruent(uint64_t left, uint64_t right, uint64_t rem, uint64_t mod)
Generates random number in range given a modular congruence.
Definition tgen.h:3227
uint64_t prime_upto(uint64_t right)
Computes largest prime up to given value.
Definition tgen.h:3142
uint64_t highly_composite_upto(uint64_t right)
Largest highly composite number up to given number.
Definition tgen.h:3095
uint64_t congruent_upto(uint64_t right, std::vector< uint64_t > rems, std::vector< uint64_t > mods)
Computes largest congruent up to given value.
Definition tgen.h:3288
std::vector< std::pair< uint64_t, int > > factor_by_prime(uint64_t n)
Factors a number into primes and its powers.
Definition tgen.h:2969
const std::vector< uint64_t > & fibonacci()
Fetches Fibonacci numbers.
Definition tgen.h:3340
uint64_t modular_inverse(uint64_t a, uint64_t mod)
Computes modular inverse.
Definition tgen.h:2984
uint64_t congruent_from(uint64_t left, uint64_t rem, uint64_t mod)
Computes smallest congruent from given value.
Definition tgen.h:3279
const std::vector< uint64_t > & highly_composites()
Fetches highly composite numbers.
Definition tgen.h:3055
std::vector< std::vector< T > > partition_elements(std::vector< T > elements, int k, int min_size=0, std::optional< uint64_t > max_size=std::nullopt)
Partitions a vector into k ordered groups.
Definition tgen.h:3667
std::vector< uint64_t > gen_partition_fixed_size_fast(uint64_t n, int k, uint64_t part_left=0, std::optional< uint64_t > part_right=std::nullopt)
Generates a fast non-uniform partition with fixed size.
Definition tgen.h:3576
uint64_t gen_congruent(uint64_t left, uint64_t right, std::vector< uint64_t > rems, std::vector< uint64_t > mods)
Generates random number in range given modular congruences.
Definition tgen.h:3177
std::pair< uint64_t, uint64_t > prime_gap_upto(uint64_t right)
Largest prime gap up to given number.
Definition tgen.h:3036
std::string gen_parenthesis(int size)
Generates a random valid parenthesis sequence.
Definition tgen.h:8902
T opt(const std::string &key, std::optional< T > default_value=std::nullopt)
Gets opt by key.
Definition tgen.h:1669
void set_compiler(compiler_value compiler)
Sets compiler.
Definition tgen.h:1417
T opt(size_t index, std::optional< T > default_value=std::nullopt)
Gets opt by key.
Definition tgen.h:1655
bool has_opt(std::size_t index)
Checks if opt at some index exists.
Definition tgen.h:1637
bool has_opt(const std::string &key)
Checks if opt with some key exists.
Definition tgen.h:1643
void set_cpp_version(int version)
Sets C++ version.
Definition tgen.h:1398
void register_gen(std::optional< long long > seed=std::nullopt)
Sets up the generator without arguments.
Definition tgen.h:1696
void register_gen(int argc, char **argv)
Sets up the generator.
Definition tgen.h:1685
wtree< VWeight, int > vtree
Vertex-weighted labeled trees.
Definition tgen.h:5361
wtree< int, EWeight > etree
Edge-weighted labeled trees.
Definition tgen.h:5364
wtree< int, int > tree
Unweighted labeled trees.
Definition tgen.h:5367
Compiler identity and version.
Definition tgen.h:288
Distinct generator for containers.
Definition tgen.h:1331
auto gen_list(int size)
Generates a list of several distinct elements.
Definition tgen.h:1353
T gen()
Generates a distinct random element from the container.
Definition tgen.h:1349
distinct_container(const C &container)
Creates distinct generator for elements of the given container.
Definition tgen.h:1337
auto gen_all()
Generates all distinct elements left to generate.
Definition tgen.h:1362
size_t size() const
Returns the number of elements left to generate.
Definition tgen.h:1345
Distinct generator for integral ranges.
Definition tgen.h:1158
auto gen_list(int count)
Generates a list of several distinct values.
Definition tgen.h:1214
distinct_range(T left, T right)
Creates distinct generator for values in given range.
Definition tgen.h:1175
auto gen_all()
Generates all distinct values left to generate.
Definition tgen.h:1267
T gen()
Generates a distinct random value in the defined range.
Definition tgen.h:1184
count_type size() const
Returns the number of values left to generate.
Definition tgen.h:1179
Distinct generator for discrete uniform functions.
Definition tgen.h:326
distinct(Func func, Args... args)
Generates a distinct generator of a discrete uniform function.
Definition tgen.h:332
auto gen_list(int size)
Generates a list of several distinct values.
Definition tgen.h:366
bool empty()
Checks if there is nothing left to generate.
Definition tgen.h:377
auto gen_all()
Generates all distinct values left to generate.
Definition tgen.h:380
auto gen()
Generates a distinct value.
Definition tgen.h:354
Base class for generators (should not be instantiated).
Definition tgen.h:413
auto gen_list(int size, Args &&...args) const
Generates a list of several generation calls.
Definition tgen.h:416
auto gen_until(Pred predicate, int max_tries, Args &&...args) const
Generates a random value from the valid set until a condition is met.
Definition tgen.h:428
auto distinct(Args &&...args) const
Creates distinct generator for current generator.
Definition tgen.h:447
Base class for generator values (should not be instantiated).
Definition tgen.h:470
bool operator<(const Val &rhs) const
Definition tgen.h:473
Point on the plane.
Definition tgen.h:6903
T x() const
x coordinate.
Definition tgen.h:6920
bool operator==(const point &p) const
Coordinate-wise equality.
Definition tgen.h:6936
product_t operator*(const point &p) const
Dot product.
Definition tgen.h:6954
product_t operator^(const point &p) const
Cross product.
Definition tgen.h:6972
point operator*(T c) const
Scalar multiplication.
Definition tgen.h:6951
point operator-(const point &p) const
Vector subtraction.
Definition tgen.h:6946
point(T x=0, T y=0)
Constructs a point.
Definition tgen.h:6917
T y() const
y coordinate.
Definition tgen.h:6923
bool operator<(const point &p) const
Lexicographic order.
Definition tgen.h:6929
point operator+(const point &p) const
Vector addition.
Definition tgen.h:6941
List value.
Definition tgen.h:1874
int size() const
Returns the size of the list value.
Definition tgen.h:1888
value(const std::vector< T > &vec)
Creates a list value from a std::vector.
Definition tgen.h:1883
value & sort()
Sorts the list in non-decreasing order.
Definition tgen.h:1904
auto to_std() const
Converts the list to a std::vector.
Definition tgen.h:1985
value & separator(char sep)
Sets separator for printing.
Definition tgen.h:1918
value choose(int k) const
Chooses a uniformly random subsequence of given length.
Definition tgen.h:1959
value operator+(const value &rhs) const
Concatenates two lists.
Definition tgen.h:1925
T & operator[](int idx)
Accesses the element at some position of the list.
Definition tgen.h:1891
value & reverse()
Reverses the list.
Definition tgen.h:1911
T pick_by_distribution(const std::vector< Dist > &distribution) const
Returns a random element from the list with given probabilities.
Definition tgen.h:1946
value & shuffle()
Shuffles the list in place.
Definition tgen.h:1934
T pick() const
Returns a uniformly random element.
Definition tgen.h:1941
List generator.
Definition tgen.h:1720
list & different(int idx_1, int idx_2)
Restricts generator s.t. values at two indices are different.
Definition tgen.h:1844
list & equal(int idx_1, int idx_2)
Restricts generator s.t. values at two indices are equal.
Definition tgen.h:1792
list & adjacent_different()
Restricts generator s.t. adjacent values are different.
Definition tgen.h:1866
list & all_different()
Restricts generator s.t. all values are different.
Definition tgen.h:1859
list & equal_range(int left, int right)
Restricts generator s.t. all values at index range are equal.
Definition tgen.h:1820
list(int size, std::set< T > values)
Creates list generator defined by value set.
Definition tgen.h:1752
value gen() const
Generates a uniformly random value from the set of valid lists.
Definition tgen.h:2000
list & all_equal()
Restricts generator s.t. all values are equal.
Definition tgen.h:1829
list & different(std::set< int > indices)
Restricts generator s.t. all values in index set are different.
Definition tgen.h:1834
list & different_range(int left, int right)
Restricts generator s.t. all values at index range are different.
Definition tgen.h:1850
list(int size, T value_left, T value_right)
Creates list generator defined by size and range of values.
Definition tgen.h:1744
list & fix(int idx, T val)
Restricts generator s.t. value at index is fixed.
Definition tgen.h:1764
list & equal(std::set< int > indices)
Restricts generator s.t. all values in index set are equal.
Definition tgen.h:1808
Pair value.
Definition tgen.h:4529
T second() const
Returns the second element of a pair value.
Definition tgen.h:4541
value(const T &first, const T &second)
Creates a pair value from first and second values.
Definition tgen.h:4537
value(const std::pair< T, T > &pair)
Creates a pair value from a std::pair.
Definition tgen.h:4536
auto to_std() const
Converts the pair to a std::pair.
Definition tgen.h:4555
T first() const
Returns the first element of a pair value.
Definition tgen.h:4540
value & separator(char sep)
Sets separator for printing.
Definition tgen.h:4544
Pair generator.
Definition tgen.h:4472
value gen() const
Generates a uniformly random value from the set of valid pairs.
Definition tgen.h:4568
pair & neq()
Restricts generator s.t. first is not equal to second.
Definition tgen.h:4499
pair & leq()
Restricts generator s.t. first is less than or equal to second.
Definition tgen.h:4517
pair & lt()
Restricts generator s.t. first is less than second.
Definition tgen.h:4505
pair & gt()
Restricts generator s.t. first is greater than second.
Definition tgen.h:4511
pair(T both_left, T both_right)
Creates pair generator defined by range of values for both first and second.
Definition tgen.h:4489
pair & eq()
Restricts generator s.t. first is equal to second.
Definition tgen.h:4493
pair(T first_left, T first_right, T second_left, T second_right)
Creates pair generator defined by range of values for first and second.
Definition tgen.h:4480
pair & geq()
Restricts generator s.t. first is greater than or equal to second.
Definition tgen.h:4523
Permutation value.
Definition tgen.h:2457
value & print_1_based()
Sets that printed values are 1-based.
Definition tgen.h:2543
std::vector< int > to_std() const
Converts the permutation to a std::vector.
Definition tgen.h:2585
const int & operator[](int idx) const
Returns the image at some position of the permutation.
Definition tgen.h:2486
std::vector< int > to_std_1_based() const
Converts the permutation to a 1-based std::vector.
Definition tgen.h:2589
value & sort()
Sorts the permutation in non-decreasing order.
Definition tgen.h:2510
int parity() const
Parity of the permutation.
Definition tgen.h:2494
int pick_by_distribution(const std::vector< Dist > &distribution) const
Returns a random element from the permutation with given probabilities.
Definition tgen.h:2562
int pick() const
Returns a uniformly random element.
Definition tgen.h:2557
value & reverse()
Reverses the permutation.
Definition tgen.h:2518
value(const std::vector< int > &vec)
Creates a permutation value from a std::vector.
Definition tgen.h:2465
int size() const
Returns the size of the permutation value.
Definition tgen.h:2483
value & shuffle()
Shuffles the permutation.
Definition tgen.h:2550
value & inverse()
Inverse of the permutation.
Definition tgen.h:2525
value & separator(char sep)
Sets separator for printing.
Definition tgen.h:2535
Permutation generator.
Definition tgen.h:2414
value gen() const
Generates a uniformly random value from the set of valid permutations.
Definition tgen.h:2599
permutation & cycles(const std::vector< int > &cycle_sizes)
Restricts generator s.t. cycle sizes are fixed.
Definition tgen.h:2433
permutation(int size)
Creates permutation generator defined by size.
Definition tgen.h:2420
permutation & fix(int idx, int val)
Restricts generator s.t. value at index is fixed.
Definition tgen.h:2425
Printer helper for printing containers or sequential generator elements as columns.
Definition tgen.h:622
print_cols(const Args &...args)
Creates a printer object that prints as columns.
Definition tgen.h:625
Printer helper for standard types.
Definition tgen.h:492
print(const T &val, char sep=' ')
Creates a printer object.
Definition tgen.h:495
Printer helper for standard types, printing on a new line.
Definition tgen.h:597
println(const T &val, char sep=' ')
Creates a printer object that prints on a new line.
Definition tgen.h:599
String value.
Definition tgen.h:4134
char pick() const
Returns a uniformly random element.
Definition tgen.h:4205
char pick_by_distribution(const std::vector< Dist > &distribution) const
Returns a random element from the string with given probabilities.
Definition tgen.h:4210
value choose(int k) const
Chooses a uniformly random subsequence of given length.
Definition tgen.h:4223
value & lowercase()
Sets all characters to lowercase.
Definition tgen.h:4174
value & reverse()
Reverses the string.
Definition tgen.h:4167
int size() const
Returns the size of the string value.
Definition tgen.h:4144
value(const std::string &str)
Creates a string value from a std::string.
Definition tgen.h:4141
value & shuffle()
Shuffles the string.
Definition tgen.h:4198
char & operator[](int idx)
Accesses the character at some position of the string.
Definition tgen.h:4147
value & uppercase()
Sets all characters to uppercase.
Definition tgen.h:4183
value operator+(const value &rhs) const
Concatenates two strings.
Definition tgen.h:4192
std::string to_std() const
Converts the string to a std::string.
Definition tgen.h:4244
value & sort()
Sorts the characters in non-decreasing order.
Definition tgen.h:4160
String generator.
Definition tgen.h:4019
str & different(int idx_1, int idx_2)
Restricts generator s.t. characters at two indices are different.
Definition tgen.h:4106
str & palindrome(int left, int right)
Restricts generator s.t. range is a palindrome.
Definition tgen.h:4082
value gen() const
Generates a uniformly random value from the set of valid strings.
Definition tgen.h:4250
str(int size, char value_left='a', char value_right='z')
Creates string generator defined by size and range of characters.
Definition tgen.h:4026
str & different(std::set< int > indices)
Restricts generator s.t. all characters in index set are different.
Definition tgen.h:4099
str(const std::string &regex, Args &&...args)
Creates string generator defined by regex.
Definition tgen.h:4039
str & equal(int idx_1, int idx_2)
Restricts generator s.t. characters at two indices are equal.
Definition tgen.h:4061
str & equal(std::set< int > indices)
Restricts generator s.t. all characters in index set are equal.
Definition tgen.h:4054
str & equal_range(int left, int right)
Restricts generator s.t. all characters at index range are equal.
Definition tgen.h:4068
str & fix(int idx, char character)
Restricts generator s.t. character at index is fixed.
Definition tgen.h:4047
str & all_equal()
Restricts generator s.t. all values are equal.
Definition tgen.h:4075
str & different_range(int left, int right)
Restricts generator s.t. all characters at index range are different.
Definition tgen.h:4113
str & palindrome()
Restricts generator s.t. string is a palindrome.
Definition tgen.h:4092
str & all_different()
Restricts generator s.t. all characters are different.
Definition tgen.h:4120
str(int size, std::set< char > chars)
Creates string generator defined by character set.
Definition tgen.h:4033
str & adjacent_different()
Restricts generator s.t. adjacent values are different.
Definition tgen.h:4127
Sampler for repeated draws from a fixed weighted distribution.
Definition tgen.h:889
size_t next() const
Generates a random index with probability proportional to the distribution.
Definition tgen.h:1015
weighted_sampler(const std::vector< T > &distribution)
Creates a weighted sampler from a probability distribution.
Definition tgen.h:906
Labeled graph value.
Definition tgen.h:5553
value & print_nm()
Prints number of vertices and edges before edge list.
Definition tgen.h:5726
const std::optional< std::vector< VWeight > > & vertex_weights() const
Optional vertex weights.
Definition tgen.h:5666
value operator!() const
Graph complement of unweighted graph.
Definition tgen.h:6133
std::tuple< int, int, std::vector< std::set< int > > > to_std() const
Converts the graph to std types.
Definition tgen.h:6224
value & shuffle_except(std::set< int > indices)
Shuffles vertices except given vertices, and edge order.
Definition tgen.h:5736
int n() const
Number of vertices.
Definition tgen.h:5648
value operator+(const value &rhs) const
Concatenates two graphs (disjoint union).
Definition tgen.h:6167
value & disjoint_union(const value &rhs)
Disjoint union with another graph.
Definition tgen.h:6000
int m() const
Number of edges.
Definition tgen.h:5651
std::tuple< int, int, std::vector< std::set< int > > > to_std_1_based() const
Converts the graph to 1-based std types.
Definition tgen.h:6232
value & glue(const value &rhs, std::set< std::pair< int, int > > index_pairs)
Glues another graph at given vertex pairs.
Definition tgen.h:5915
const std::optional< std::vector< EWeight > > & edge_weights() const
Optional edge weights.
Definition tgen.h:5671
value(const std::vector< std::set< int > > &adj, bool is_directed=false)
Builds a graph from an adjacency list.
Definition tgen.h:5572
value(int n, const std::vector< std::pair< int, int > > &edges={}, bool is_directed=false)
Builds a graph from number of vertices and edge list.
Definition tgen.h:5593
wgraph< NewVWeight, EWeight >::value set_vertex_weights(const std::vector< NewVWeight > &vertex_weights) const
Attaches vertex weights.
Definition tgen.h:5678
const std::vector< std::set< int > > & adj() const
Adjacency list.
Definition tgen.h:5657
value & add_vertices(int k, std::optional< std::vector< VWeight > > new_vertex_weights=std::nullopt)
Adds new isolated vertices.
Definition tgen.h:5807
value & print_1_based()
Sets that printed vertex ids are 1-based.
Definition tgen.h:5719
value & random_connected_subgraph(int num_edges)
Random subgraph with a fixed number of edges that keeps components connected.
Definition tgen.h:6042
value(const typename wtree< VWeight, EWeight >::value &t)
Builds an undirected graph from a tree.
Definition tgen.h:5624
value & random_subgraph(int num_edges)
Random subgraph with a fixed number of edges.
Definition tgen.h:6006
value & edge_weighted()
Enables edge-weighted mode on an edgeless graph.
Definition tgen.h:5705
value & link(const value &rhs, int new_u, int new_v, std::optional< EWeight > new_w=std::nullopt)
Links two graphs by an new edge.
Definition tgen.h:5878
bool is_directed() const
If the graph is directed.
Definition tgen.h:5654
value & add_edge(int u, int v, std::optional< EWeight > w=std::nullopt)
Adds an edge between two vertices.
Definition tgen.h:5842
value & shuffle()
Shuffles all vertices and edge order.
Definition tgen.h:5802
wgraph< VWeight, NewEWeight >::value set_edge_weights(const std::vector< NewEWeight > &edge_weights) const
Attaches edge weights.
Definition tgen.h:5693
const std::vector< std::pair< int, int > > & edges() const
Edge list.
Definition tgen.h:5663
Labeled weighted graph generator.
Definition tgen.h:5511
wgraph(int n, int m, bool is_directed=false, bool has_self_loops=false)
Creates a graph generator for a fixed number of vertices and edges.
Definition tgen.h:5521
static value gen_bipartite(int n1, int n2, int m, bool connected=false)
Generates a random bipartite graph.
Definition tgen.h:6600
value get_connected() const
Random connected undirected graph extending preset edges.
Definition tgen.h:6320
static value gen_np(int n, double p, bool is_directed=false, bool has_self_loops=false)
Generates a random graph where each edge is included independently.
Definition tgen.h:6687
value gen() const
Generates a uniformly random graph satisfying the constraints.
Definition tgen.h:6296
wgraph & add_edge(int u, int v)
Adds a preset edge that must appear in the generated graph.
Definition tgen.h:5529
value get_acyclic() const
Random directed acyclic graph extending preset edges.
Definition tgen.h:6394
static value gen_skewed(int n, int m, int elongation, int spread, bool is_directed=false)
Random skewed connected graph (large diameter).
Definition tgen.h:6496
wgraph & add_edges_from(const value &rhs)
Adds all edges from another graph as preset edges.
Definition tgen.h:6283
Labeled tree value.
Definition tgen.h:4719
value & glue(const value &rhs, std::set< std::pair< int, int > > index_pairs)
Glues another tree at given vertex pairs.
Definition tgen.h:5029
const std::vector< std::pair< int, int > > & edges() const
Edge list.
Definition tgen.h:4802
value(int n, const std::vector< std::pair< int, int > > &edges)
Builds a tree from a vertex count and an edge list.
Definition tgen.h:4756
value(const typename wgraph< VWeight, EWeight >::value &g)
Builds a tree from a graph via a Kruskal-like random spanning tree.
Definition tgen.h:6780
value & print_parents(int root=-1)
Prints in parent format instead of edge list.
Definition tgen.h:4875
const std::optional< std::vector< VWeight > > & vertex_weights() const
Optional vertex weights.
Definition tgen.h:4805
value & edge_weighted()
Enables edge-weighted mode on an edgeless tree.
Definition tgen.h:4845
int n() const
Returns the number of vertices.
Definition tgen.h:4796
value & shuffle_except(std::set< int > indices)
Shuffles vertices except given vertices, and edge order.
Definition tgen.h:4887
const std::vector< std::set< int > > & adj() const
Adjacency list.
Definition tgen.h:4799
value(const std::vector< std::set< int > > &adj)
Builds a tree from an adjacency list.
Definition tgen.h:4736
const std::optional< std::vector< EWeight > > & edge_weights() const
Optional edge weights.
Definition tgen.h:4810
value & shuffle()
Shuffles vertices and edge order.
Definition tgen.h:4956
std::pair< int, std::vector< std::set< int > > > to_std() const
Converts the tree to a std types.
Definition tgen.h:5200
wtree< NewVWeight, EWeight >::value set_vertex_weights(const std::vector< NewVWeight > &vertex_weights) const
Attaches vertex weights.
Definition tgen.h:4817
value & print_n()
Prints the number of vertices before the tree.
Definition tgen.h:4866
std::pair< int, std::vector< std::set< int > > > to_std_1_based() const
Converts the tree to 1-based std types.
Definition tgen.h:5206
value & link(const value &rhs, int new_u, int new_v, std::optional< EWeight > new_w=std::nullopt)
Links two trees by an edge.
Definition tgen.h:4996
value & print_1_based()
Sets that printed vertex ids are 1-based.
Definition tgen.h:4859
wtree< VWeight, NewEWeight >::value set_edge_weights(const std::vector< NewEWeight > &edge_weights) const
Attaches edge weights.
Definition tgen.h:4832
Labeled weighted tree generator.
Definition tgen.h:4692
wtree & add_edge(int u, int v)
Restricts generator s.t. some edge is present.
Definition tgen.h:4704
static value gen_skewed(int n, int elongation)
Random skewed tree (large diameter).
Definition tgen.h:5326
value gen() const
Generates a uniformly random value from the set of valid trees.
Definition tgen.h:5269
wtree(int n)
Creates a tree generator with specified number of vertices.
Definition tgen.h:4698
static value gen_kruskal(int n)
Kruskal-like random labeled tree.
Definition tgen.h:5336