File indexing completed on 2025-08-28 08:27:15
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 #ifndef PCG_EXTRAS_HPP_INCLUDED
0034 #define PCG_EXTRAS_HPP_INCLUDED 1
0035
0036 #include <cinttypes>
0037 #include <cstddef>
0038 #include <cstdlib>
0039 #include <cstring>
0040 #include <cassert>
0041 #include <limits>
0042 #include <iostream>
0043 #include <type_traits>
0044 #include <utility>
0045 #include <locale>
0046 #include <iterator>
0047
0048 #ifdef __GNUC__
0049 #include <cxxabi.h>
0050 #endif
0051
0052
0053
0054
0055
0056 #ifdef __GNUC__
0057 #define PCG_NOINLINE __attribute__((noinline))
0058 #else
0059 #define PCG_NOINLINE
0060 #endif
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077 #if __SIZEOF_INT128__ && !PCG_FORCE_EMULATED_128BIT_MATH
0078 namespace arrow_vendored {
0079 namespace pcg_extras {
0080 typedef __uint128_t pcg128_t;
0081 }
0082 }
0083 #define PCG_128BIT_CONSTANT(high,low) \
0084 ((pcg_extras::pcg128_t(high) << 64) + low)
0085 #else
0086 #include "pcg_uint128.hpp"
0087 namespace arrow_vendored {
0088 namespace pcg_extras {
0089 typedef pcg_extras::uint_x4<uint32_t,uint64_t> pcg128_t;
0090 }
0091 }
0092 #define PCG_128BIT_CONSTANT(high,low) \
0093 pcg_extras::pcg128_t(high,low)
0094 #define PCG_EMULATED_128BIT_MATH 1
0095 #endif
0096
0097
0098 namespace arrow_vendored {
0099 namespace pcg_extras {
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109 #ifndef PCG_BITCOUNT_T
0110 typedef uint8_t bitcount_t;
0111 #else
0112 typedef PCG_BITCOUNT_T bitcount_t;
0113 #endif
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124 template <typename CharT, typename Traits>
0125 std::basic_ostream<CharT,Traits>&
0126 operator<<(std::basic_ostream<CharT,Traits>& out, pcg128_t value)
0127 {
0128 auto desired_base = out.flags() & out.basefield;
0129 bool want_hex = desired_base == out.hex;
0130
0131 if (want_hex) {
0132 uint64_t highpart = uint64_t(value >> 64);
0133 uint64_t lowpart = uint64_t(value);
0134 auto desired_width = out.width();
0135 if (desired_width > 16) {
0136 out.width(desired_width - 16);
0137 }
0138 if (highpart != 0 || desired_width > 16)
0139 out << highpart;
0140 CharT oldfill = '\0';
0141 if (highpart != 0) {
0142 out.width(16);
0143 oldfill = out.fill('0');
0144 }
0145 auto oldflags = out.setf(decltype(desired_base){}, out.showbase);
0146 out << lowpart;
0147 out.setf(oldflags);
0148 if (highpart != 0) {
0149 out.fill(oldfill);
0150 }
0151 return out;
0152 }
0153 constexpr size_t MAX_CHARS_128BIT = 40;
0154
0155 char buffer[MAX_CHARS_128BIT];
0156 char* pos = buffer+sizeof(buffer);
0157 *(--pos) = '\0';
0158 constexpr auto BASE = pcg128_t(10ULL);
0159 do {
0160 auto div = value / BASE;
0161 auto mod = uint32_t(value - (div * BASE));
0162 *(--pos) = '0' + char(mod);
0163 value = div;
0164 } while(value != pcg128_t(0ULL));
0165 return out << pos;
0166 }
0167
0168 template <typename CharT, typename Traits>
0169 std::basic_istream<CharT,Traits>&
0170 operator>>(std::basic_istream<CharT,Traits>& in, pcg128_t& value)
0171 {
0172 typename std::basic_istream<CharT,Traits>::sentry s(in);
0173
0174 if (!s)
0175 return in;
0176
0177 constexpr auto BASE = pcg128_t(10ULL);
0178 pcg128_t current(0ULL);
0179 bool did_nothing = true;
0180 bool overflow = false;
0181 for(;;) {
0182 CharT wide_ch = in.get();
0183 if (!in.good())
0184 break;
0185 auto ch = in.narrow(wide_ch, '\0');
0186 if (ch < '0' || ch > '9') {
0187 in.unget();
0188 break;
0189 }
0190 did_nothing = false;
0191 pcg128_t digit(uint32_t(ch - '0'));
0192 pcg128_t timesbase = current*BASE;
0193 overflow = overflow || timesbase < current;
0194 current = timesbase + digit;
0195 overflow = overflow || current < digit;
0196 }
0197
0198 if (did_nothing || overflow) {
0199 in.setstate(std::ios::failbit);
0200 if (overflow)
0201 current = ~pcg128_t(0ULL);
0202 }
0203
0204 value = current;
0205
0206 return in;
0207 }
0208
0209
0210
0211
0212
0213
0214
0215
0216 template <typename CharT, typename Traits>
0217 std::basic_ostream<CharT,Traits>&
0218 operator<<(std::basic_ostream<CharT,Traits>&out, uint8_t value)
0219 {
0220 return out << uint32_t(value);
0221 }
0222
0223 template <typename CharT, typename Traits>
0224 std::basic_istream<CharT,Traits>&
0225 operator>>(std::basic_istream<CharT,Traits>& in, uint8_t& target)
0226 {
0227 uint32_t value = 0xdecea5edU;
0228 in >> value;
0229 if (!in && value == 0xdecea5edU)
0230 return in;
0231 if (value > uint8_t(~0)) {
0232 in.setstate(std::ios::failbit);
0233 value = ~0U;
0234 }
0235 target = uint8_t(value);
0236 return in;
0237 }
0238
0239
0240
0241
0242
0243
0244 inline std::ostream& operator<<(std::ostream& out, uint8_t value)
0245 {
0246 return pcg_extras::operator<< <char>(out, value);
0247 }
0248
0249 inline std::istream& operator>>(std::istream& in, uint8_t& value)
0250 {
0251 return pcg_extras::operator>> <char>(in, value);
0252 }
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266 template <typename itype>
0267 inline itype unxorshift(itype x, bitcount_t bits, bitcount_t shift)
0268 {
0269 if (2*shift >= bits) {
0270 return x ^ (x >> shift);
0271 }
0272 itype lowmask1 = (itype(1U) << (bits - shift*2)) - 1;
0273 itype highmask1 = ~lowmask1;
0274 itype top1 = x;
0275 itype bottom1 = x & lowmask1;
0276 top1 ^= top1 >> shift;
0277 top1 &= highmask1;
0278 x = top1 | bottom1;
0279 itype lowmask2 = (itype(1U) << (bits - shift)) - 1;
0280 itype bottom2 = x & lowmask2;
0281 bottom2 = unxorshift(bottom2, bits - shift, shift);
0282 bottom2 &= lowmask1;
0283 return top1 | bottom2;
0284 }
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295 template <typename itype>
0296 inline itype rotl(itype value, bitcount_t rot)
0297 {
0298 constexpr bitcount_t bits = sizeof(itype) * 8;
0299 constexpr bitcount_t mask = bits - 1;
0300 #if PCG_USE_ZEROCHECK_ROTATE_IDIOM
0301 return rot ? (value << rot) | (value >> (bits - rot)) : value;
0302 #else
0303 return (value << rot) | (value >> ((- rot) & mask));
0304 #endif
0305 }
0306
0307 template <typename itype>
0308 inline itype rotr(itype value, bitcount_t rot)
0309 {
0310 constexpr bitcount_t bits = sizeof(itype) * 8;
0311 constexpr bitcount_t mask = bits - 1;
0312 #if PCG_USE_ZEROCHECK_ROTATE_IDIOM
0313 return rot ? (value >> rot) | (value << (bits - rot)) : value;
0314 #else
0315 return (value >> rot) | (value << ((- rot) & mask));
0316 #endif
0317 }
0318
0319
0320
0321
0322
0323
0324
0325
0326 #if PCG_USE_INLINE_ASM && __GNUC__ && (__x86_64__ || __i386__)
0327
0328 inline uint8_t rotr(uint8_t value, bitcount_t rot)
0329 {
0330 asm ("rorb %%cl, %0" : "=r" (value) : "0" (value), "c" (rot));
0331 return value;
0332 }
0333
0334 inline uint16_t rotr(uint16_t value, bitcount_t rot)
0335 {
0336 asm ("rorw %%cl, %0" : "=r" (value) : "0" (value), "c" (rot));
0337 return value;
0338 }
0339
0340 inline uint32_t rotr(uint32_t value, bitcount_t rot)
0341 {
0342 asm ("rorl %%cl, %0" : "=r" (value) : "0" (value), "c" (rot));
0343 return value;
0344 }
0345
0346 #if __x86_64__
0347 inline uint64_t rotr(uint64_t value, bitcount_t rot)
0348 {
0349 asm ("rorq %%cl, %0" : "=r" (value) : "0" (value), "c" (rot));
0350 return value;
0351 }
0352 #endif
0353
0354 #elif defined(_MSC_VER)
0355
0356
0357 #pragma intrinsic(_rotr, _rotr64, _rotr8, _rotr16)
0358
0359 inline uint8_t rotr(uint8_t value, bitcount_t rot)
0360 {
0361 return _rotr8(value, rot);
0362 }
0363
0364 inline uint16_t rotr(uint16_t value, bitcount_t rot)
0365 {
0366 return _rotr16(value, rot);
0367 }
0368
0369 inline uint32_t rotr(uint32_t value, bitcount_t rot)
0370 {
0371 return _rotr(value, rot);
0372 }
0373
0374 inline uint64_t rotr(uint64_t value, bitcount_t rot)
0375 {
0376 return _rotr64(value, rot);
0377 }
0378
0379 #endif
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409 template<class SrcIter, class DestIter>
0410 SrcIter uneven_copy_impl(
0411 SrcIter src_first, DestIter dest_first, DestIter dest_last,
0412 std::true_type)
0413 {
0414 typedef typename std::iterator_traits<SrcIter>::value_type src_t;
0415 typedef typename std::iterator_traits<DestIter>::value_type dest_t;
0416
0417 constexpr bitcount_t SRC_SIZE = sizeof(src_t);
0418 constexpr bitcount_t DEST_SIZE = sizeof(dest_t);
0419 constexpr bitcount_t DEST_BITS = DEST_SIZE * 8;
0420 constexpr bitcount_t SCALE = SRC_SIZE / DEST_SIZE;
0421
0422 size_t count = 0;
0423 src_t value = 0;
0424
0425 while (dest_first != dest_last) {
0426 if ((count++ % SCALE) == 0)
0427 value = *src_first++;
0428 else
0429 value >>= DEST_BITS;
0430
0431 *dest_first++ = dest_t(value);
0432 }
0433 return src_first;
0434 }
0435
0436
0437
0438 template<class SrcIter, class DestIter>
0439 SrcIter uneven_copy_impl(
0440 SrcIter src_first, DestIter dest_first, DestIter dest_last,
0441 std::false_type)
0442 {
0443 typedef typename std::iterator_traits<SrcIter>::value_type src_t;
0444 typedef typename std::iterator_traits<DestIter>::value_type dest_t;
0445
0446 constexpr auto SRC_SIZE = sizeof(src_t);
0447 constexpr auto SRC_BITS = SRC_SIZE * 8;
0448 constexpr auto DEST_SIZE = sizeof(dest_t);
0449 constexpr auto SCALE = (DEST_SIZE+SRC_SIZE-1) / SRC_SIZE;
0450
0451 while (dest_first != dest_last) {
0452 dest_t value(0UL);
0453 unsigned int shift = 0;
0454
0455 for (size_t i = 0; i < SCALE; ++i) {
0456 value |= dest_t(*src_first++) << shift;
0457 shift += SRC_BITS;
0458 }
0459
0460 *dest_first++ = value;
0461 }
0462 return src_first;
0463 }
0464
0465
0466
0467 template<class SrcIter, class DestIter>
0468 inline SrcIter uneven_copy(SrcIter src_first,
0469 DestIter dest_first, DestIter dest_last)
0470 {
0471 typedef typename std::iterator_traits<SrcIter>::value_type src_t;
0472 typedef typename std::iterator_traits<DestIter>::value_type dest_t;
0473
0474 constexpr bool DEST_IS_SMALLER = sizeof(dest_t) < sizeof(src_t);
0475
0476 return uneven_copy_impl(src_first, dest_first, dest_last,
0477 std::integral_constant<bool, DEST_IS_SMALLER>{});
0478 }
0479
0480
0481
0482
0483
0484 template <size_t size, typename SeedSeq, typename DestIter>
0485 inline void generate_to_impl(SeedSeq&& generator, DestIter dest,
0486 std::true_type)
0487 {
0488 generator.generate(dest, dest+size);
0489 }
0490
0491 template <size_t size, typename SeedSeq, typename DestIter>
0492 void generate_to_impl(SeedSeq&& generator, DestIter dest,
0493 std::false_type)
0494 {
0495 typedef typename std::iterator_traits<DestIter>::value_type dest_t;
0496 constexpr auto DEST_SIZE = sizeof(dest_t);
0497 constexpr auto GEN_SIZE = sizeof(uint32_t);
0498
0499 constexpr bool GEN_IS_SMALLER = GEN_SIZE < DEST_SIZE;
0500 constexpr size_t FROM_ELEMS =
0501 GEN_IS_SMALLER
0502 ? size * ((DEST_SIZE+GEN_SIZE-1) / GEN_SIZE)
0503 : (size + (GEN_SIZE / DEST_SIZE) - 1)
0504 / ((GEN_SIZE / DEST_SIZE) + GEN_IS_SMALLER);
0505
0506
0507
0508 if (FROM_ELEMS <= 1024) {
0509 uint32_t buffer[FROM_ELEMS];
0510 generator.generate(buffer, buffer+FROM_ELEMS);
0511 uneven_copy(buffer, dest, dest+size);
0512 } else {
0513 uint32_t* buffer = static_cast<uint32_t*>(malloc(GEN_SIZE * FROM_ELEMS));
0514 generator.generate(buffer, buffer+FROM_ELEMS);
0515 uneven_copy(buffer, dest, dest+size);
0516 free(static_cast<void*>(buffer));
0517 }
0518 }
0519
0520 template <size_t size, typename SeedSeq, typename DestIter>
0521 inline void generate_to(SeedSeq&& generator, DestIter dest)
0522 {
0523 typedef typename std::iterator_traits<DestIter>::value_type dest_t;
0524 constexpr bool IS_32BIT = sizeof(dest_t) == sizeof(uint32_t);
0525
0526 generate_to_impl<size>(std::forward<SeedSeq>(generator), dest,
0527 std::integral_constant<bool, IS_32BIT>{});
0528 }
0529
0530
0531
0532
0533
0534
0535 template <typename UInt, size_t i = 0UL, size_t N = i+1UL, typename SeedSeq>
0536 inline UInt generate_one(SeedSeq&& generator)
0537 {
0538 UInt result[N];
0539 generate_to<N>(std::forward<SeedSeq>(generator), result);
0540 return result[i];
0541 }
0542
0543 template <typename RngType>
0544 auto bounded_rand(RngType& rng, typename RngType::result_type upper_bound)
0545 -> typename RngType::result_type
0546 {
0547 typedef typename RngType::result_type rtype;
0548 rtype threshold = (RngType::max() - RngType::min() + rtype(1) - upper_bound)
0549 % upper_bound;
0550 for (;;) {
0551 rtype r = rng() - RngType::min();
0552 if (r >= threshold)
0553 return r % upper_bound;
0554 }
0555 }
0556
0557 template <typename Iter, typename RandType>
0558 void shuffle(Iter from, Iter to, RandType&& rng)
0559 {
0560 typedef typename std::iterator_traits<Iter>::difference_type delta_t;
0561 typedef typename std::remove_reference<RandType>::type::result_type result_t;
0562 auto count = to - from;
0563 while (count > 1) {
0564 delta_t chosen = delta_t(bounded_rand(rng, result_t(count)));
0565 --count;
0566 --to;
0567 using std::swap;
0568 swap(*(from + chosen), *to);
0569 }
0570 }
0571
0572
0573
0574
0575
0576
0577
0578
0579
0580
0581
0582
0583
0584 template <typename RngType>
0585 class seed_seq_from {
0586 private:
0587 RngType rng_;
0588
0589 typedef uint_least32_t result_type;
0590
0591 public:
0592 template<typename... Args>
0593 seed_seq_from(Args&&... args) :
0594 rng_(std::forward<Args>(args)...)
0595 {
0596
0597 }
0598
0599 template<typename Iter>
0600 void generate(Iter start, Iter finish)
0601 {
0602 for (auto i = start; i != finish; ++i)
0603 *i = result_type(rng_());
0604 }
0605
0606 constexpr size_t size() const
0607 {
0608 return (sizeof(typename RngType::result_type) > sizeof(result_type)
0609 && RngType::max() > ~size_t(0UL))
0610 ? ~size_t(0UL)
0611 : size_t(RngType::max());
0612 }
0613 };
0614
0615
0616
0617
0618
0619
0620
0621
0622 #if __cpp_rtti || __GXX_RTTI
0623
0624 template <typename T>
0625 struct printable_typename {};
0626
0627 template <typename T>
0628 std::ostream& operator<<(std::ostream& out, printable_typename<T>) {
0629 const char *implementation_typename = typeid(T).name();
0630 #ifdef __GNUC__
0631 int status;
0632 char* pretty_name =
0633 abi::__cxa_demangle(implementation_typename, nullptr, nullptr, &status);
0634 if (status == 0)
0635 out << pretty_name;
0636 free(static_cast<void*>(pretty_name));
0637 if (status == 0)
0638 return out;
0639 #endif
0640 out << implementation_typename;
0641 return out;
0642 }
0643
0644 #endif
0645
0646 }
0647 }
0648
0649 #endif