12#ifndef _CPG_CHRONO_RANDOM_HPP
13#define _CPG_CHRONO_RANDOM_HPP
20 #if _MSVC_LANG < 201703L
21 #error This libary requires C++17 Standard (Visual Studio 2017).
25 #if __cplusplus < 201703
26 #error This library requires C++17 Standard (GNU g++ version 8.0 or clang++ version 8.0 above)
52 namespace chrono_random
61 template<
typename TimeUnit>
62 using duration_t = std::chrono::duration<double, TimeUnit>;
72 using time_point_t = std::chrono::time_point<high_resolution_clock_t>;
81 using std::chrono::duration;
82 using std::chrono::duration_cast;
85 duration_cast<std::chrono::milliseconds>(
now().time_since_epoch());
87 return current.count();
91 template<
typename TimeUnit>
96 using std::chrono::duration;
97 using std::chrono::duration_cast;
99 if constexpr(std::is_same_v<TimeUnit, second_t>)
101 auto period_of_time =
102 duration_cast<std::chrono::duration<double, second_t>>(end_time - start_time);
103 return period_of_time.count();
107 auto period_of_time =
108 duration_cast<std::chrono::duration<double, TimeUnit>>(end_time - start_time);
110 return period_of_time.count();
116 template<std::
integral IntegralType>
118 std::uniform_int_distribution<IntegralType>;
120 template<std::
floating_po
int RealType>
122 std::uniform_real_distribution<RealType>;
136 template<
typename TimeUnit = milli_t>
139 auto rlt = time_difference_in_unit<TimeUnit>(this->m_start_time,
now());
144 template<
typename TimeUnit = milli_t>
145 std::string
elapsed_time(
bool bReset =
true, TimeUnit dummy_time = TimeUnit{})
const
147 std::ostringstream os;
149 os << time_difference_in_unit<TimeUnit>(this->m_start_time,
now());
151 if constexpr(std::is_same_v<TimeUnit, nano_t>)
152 os <<
" nano-seconds";
153 else if constexpr(std::is_same_v<TimeUnit, micro_t>)
154 os <<
" micro-seconds";
155 else if constexpr(std::is_same_v<TimeUnit, milli_t>)
156 os <<
" milli-seconds";
157 else if constexpr(std::is_same_v<TimeUnit, second_t>)
159 else if constexpr(std::is_same_v<TimeUnit, minute_t>)
161 else if constexpr(std::is_same_v<TimeUnit, hour_t>)
169 template<std::
integral Type>
174 std::random_device m_rd;
175 std::mt19937 m_randomizer;
176 typename std::vector<Type>::iterator m_next;
177 std::vector<Type> m_array;
182 m_array((
end-start)*instance), m_rd{}, m_randomizer{ m_rd() }
184 auto diff =
end - start;
186 for(
size_t i = 0; i < m_array.size(); ++i )
187 m_array[i] = (i % diff) + start;
192 typename std::vector<Type>::iterator
begin() {
return this->m_array.begin(); };
193 typename std::vector<Type>::iterator
end() {
return this->m_array.end(); };
194 typename std::vector<Type>::iterator
next() {
return this->m_next; };
196 size_t size() {
return m_array.size(); }
200 std::shuffle(m_array.begin(), m_array.end(), m_randomizer);
201 this->m_next = m_array.begin();
206 if(this->m_next == m_array.end())
209 Type v = *this->m_next;
216 return this->m_array;
220 template<
typename Type,
221 typename DistributionType,
typename EngineType>
228 mutable Type m_range_start;
229 mutable Type m_range_end;
235 Type range_end = Type{100},
236 unsigned int seed = 0):
237 m_range_start{range_start},
238 m_range_end{range_end},
240 m_distribution{range_start, range_end} {}
247 return m_distribution(m_engine);
250 template<
typename SizeType>
253 template<
typename SizeType>
257 template<std::
integral IntegralType>
261 template<std::
floating_po
int RealType>
265 template<
typename ValueType,
typename RangeType1,
typename RangeType2>
268 if constexpr(std::is_integral_v<ValueType>)
275 else if constexpr(std::floating_point<ValueType>)
284 template<
typename Type,
285 typename DistributionType,
typename EngineType>
286 template<
typename SizeType>
292 std::vector<random_type> randoms;
293 randoms.reserve((
size_t)size);
296 random_generator<unsigned>((
unsigned)1,
297 std::numeric_limits<unsigned>::max());
299 std::set<unsigned> seeds;
300 while(seeds.size() != (
size_t)size)
302 seeds.insert(generator());
305 for(
auto seed: seeds)
306 randoms.emplace_back(random_type{this->m_range_start,
307 this->m_range_end,
seed});
312 template<
typename Type,
313 typename DistributionType,
typename EngineType>
314 template<
typename SizeType>
319 using random_pair = std::pair<size_t, random_type>;
321 std::vector<random_pair> randoms;
322 randoms.reserve((
size_t)size);
325 random_generator<unsigned>((
unsigned)1,
326 std::numeric_limits<unsigned>::max());
328 std::set<unsigned> seeds;
329 while(seeds.size() != (
size_t)size)
331 seeds.insert(generator());
336 for(
auto seed: seeds)
337 randoms.emplace_back(index++, random_type{this->m_range_start,
338 this->m_range_end,
seed});
343 template<
typename Type, std::
size_t N,
typename RandomGeneratorType>
346 for(
auto& e: container)
350 template<
typename Type, std::
size_t M, std::
size_t N,
typename RandomGeneratorType>
353 using array_t = Type[M * N];
354 auto& array = (array_t&)container[0][0];
359 template<
typename Type, std::
size_t L, std::
size_t M, std::
size_t N,
typename RandomGeneratorType>
362 using array_t = Type[L * M * N];
363 auto& array = (array_t&)container[0][0];
368 template<
template<
typename,
typename...>
class ContainerType,
369 typename Type,
typename... Types,
typename RType,
370 template<
typename,
typename...>
class RandomGeneratorType,
typename... RTypes>
374 if(container.empty())
377 for(
auto& e: container)
381 template<
template<
typename,
typename...>
class ContainerType,
382 typename Type,
typename... Types,
typename RandomGeneratorType>
386 if(container.empty())
389 for(
auto& e: container)
393 template<
template<
typename,
typename...>
class ContainerType,
394 typename Type,
typename... Types,
typename RangeType>
396 RangeType range_start, RangeType range_end)
398 random_fill(container, random_generator<RangeType>(range_start, range_end));
402 template<
template<
typename, std::
size_t>
class ContainerType,
403 typename Type, std::size_t N,
typename RType,
404 template<
typename,
typename...>
class RandomGeneratorType,
typename... RTypes>
408 if(container.empty())
411 for(
auto& e: container)
415 template<
template<
typename, std::
size_t>
class ContainerType,
416 typename Type, std::size_t N,
typename RandomGeneratorType>
420 if(container.empty())
423 for(
auto& e: container)
427 template<
template<
typename, std::
size_t>
class ContainerType,
428 typename Type, std::size_t N,
typename RangeType>
430 RangeType range_start, RangeType range_end)
432 random_fill(container, random_generator<RangeType>(range_start, range_end));
437 template<
typename Type, std::size_t N,
438 template<
typename,
typename...>
class RandomGeneratorType,
typename RType,
typename... RTypes>
442 size_t container_size = N;
443 size_t generator_size = std::thread::hardware_concurrency();
444 size_t span = container_size / generator_size;
452 if(container_size % generator_size ) ++generator_size;
454 auto generator_pairs =
457 std::for_each(std::execution::par,
458 generator_pairs.begin(), generator_pairs.end(),
461 auto index_start = pair.first * span;
462 auto index_end = index_start + span;
464 if(index_end > container_size) index_end = container_size;
466 for(size_t i = index_start; i < index_end; ++i)
467 container[i] = (Type)pair.second();
471 template<
typename Type, std::size_t M, std::size_t N,
472 template<
typename,
typename...>
class RandomGeneratorType,
typename RType,
typename... RTypes>
476 using array_t = Type[M * N];
477 auto& array = (array_t&)container[0][0];
482 template<
typename Type, std::size_t L, std::size_t M, std::size_t N,
483 template<
typename,
typename...>
class RandomGeneratorType,
typename RType,
typename... RTypes>
487 using array_t = Type[L * M * N];
488 auto& array = (array_t&)container[0][0][0];
493 template<
template<
typename,
typename...>
class ContainerType,
494 typename Type,
typename... Types,
typename RType,
495 template<
typename,
typename...>
class RandomGeneratorType,
typename... RTypes>
499 if(container.empty())
return;
501 size_t container_size = container.size();
502 size_t generator_size = std::thread::hardware_concurrency();
503 size_t span = container_size / generator_size;
511 if(container_size % generator_size ) ++generator_size;
515 std::for_each(std::execution::par,
516 generator_pairs.begin(), generator_pairs.end(),
519 auto index_start = pair.first * span;
520 auto index_end = index_start + span;
522 if(index_end > container_size) index_end = container_size;
524 for(size_t i = index_start; i < index_end; ++i)
525 container[i] = (RType)pair.second();
529 template<
template<
typename,
typename...>
class ContainerType,
530 typename Type,
typename... Types,
531 typename RandomGeneratorType>
535 if(container.empty())
return;
537 size_t container_size = container.size();
538 size_t generator_size = std::thread::hardware_concurrency();
539 size_t span = container_size / generator_size;
547 if(container_size % generator_size ) ++generator_size;
551 std::for_each(std::execution::par,
552 generator_pairs.begin(), generator_pairs.end(),
555 auto index_start = pair.first * span;
556 auto index_end = index_start + span;
558 if(index_end > container_size) index_end = container_size;
560 for(size_t i = index_start; i < index_end; ++i)
561 container[i] = (Type)pair.second();
565 template<
template<
typename,
typename...>
class ContainerType,
566 typename Type,
typename... Types,
typename RangeType>
568 RangeType range_start, RangeType range_end)
571 random_generator<RangeType>(range_start, range_end));
575 template<
template<
typename, std::
size_t>
class ContainerType,
576 typename Type, std::size_t N,
typename RType,
577 template<
typename,
typename...>
class RandomGeneratorType,
typename... RTypes>
581 if(container.empty())
return;
583 size_t container_size = container.size();
584 size_t generator_size = std::thread::hardware_concurrency();
585 size_t span = container_size / generator_size;
593 if(container_size % generator_size ) ++generator_size;
597 std::for_each(std::execution::par,
598 generator_pairs.begin(), generator_pairs.end(),
601 auto index_start = pair.first * span;
602 auto index_end = index_start + span;
604 if(index_end > container_size) index_end = container_size;
606 for(size_t i = index_start; i < index_end; ++i)
607 container[i] = (Type)pair.second();
611 template<
template<
typename, std::
size_t>
class ContainerType,
612 typename Type, std::size_t N,
typename RandomGeneratorType>
616 if(container.empty())
return;
618 size_t container_size = container.size();
619 size_t generator_size = std::thread::hardware_concurrency();
620 size_t span = container_size / generator_size;
628 if(container_size % generator_size ) ++generator_size;
632 std::for_each(std::execution::par,
633 generator_pairs.begin(), generator_pairs.end(),
636 auto index_start = pair.first * span;
637 auto index_end = index_start + span;
639 if(index_end > container_size) index_end = container_size;
641 for(size_t i = index_start; i < index_end; ++i)
642 container[i] = (Type)pair.second();
646 template<
template<
typename, std::
size_t>
class ContainerType,
647 typename Type, std::size_t N,
typename RangeType>
649 RangeType range_start, RangeType range_end)
652 random_generator<RangeType>(range_start, range_end));
672 template<
template<
typename,
typename...>
class ContainerType,
673 typename Type,
typename... Types,
typename SizeType,
674 template<
typename,
typename...>
class RandomGeneratorType,
typename... RTypes>
676 const RandomGeneratorType<Type, RTypes...>&
random_generator, SizeType size)
678 if constexpr (cgt::resize_available_c<ContainerType<Type, Types...>>)
680 container.resize((
size_t)size);
682 for(
auto& e: container)
689 while(container.size() != size)
696 template<
typename CharType,
size_t Size>
707 template<
typename Type,
size_t ArraySize>
709 const Type(&alphabet)[ArraySize]):
710 m_alphabet{alphabet},
718 if constexpr(std::is_same_v<CharType, char>)
720 std::basic_ostringstream<CharType>
stream;
722 auto word_count = m_wordcount_selector();
724 for(
size_t j = 0; j < word_count; ++j)
726 auto length = this->m_length_selector();
728 std::basic_string<CharType> text(length,
' ');
730 for(
size_t i=0; i < length; ++i)
731 text[i] = m_alphabet[m_character_selector()];
735 if(j + 1 != (
size_t)word_count)
stream <<
' ';
742 std::basic_ostringstream<CharType>
stream;
744 auto word_count = m_wordcount_selector();
746 for(
size_t j = 0; j < word_count; ++j)
748 auto length = this->m_length_selector();
750 std::basic_string<CharType> text(length, L
' ');
752 for(
size_t i=0; i < length; ++i)
753 text[i] = m_alphabet[m_character_selector()];
757 if(j + 1 != (
size_t)word_count)
stream << L
' ';
769 template<
typename Type,
size_t ArraySize>
std::vector< Type >::iterator begin()
const std::vector< Type > & array()
std::vector< Type >::iterator next()
std::vector< Type >::iterator end()
fair_dice(Type start, Type end, Type instance=1)
auto clone(SizeType size) const
DistributionType distribution_type
random_t(const random_t &)=default
auto clone_pair(SizeType size) const
random_t(Type range_start=Type{}, Type range_end=Type{100}, unsigned int seed=0)
random_t & operator=(const random_t &)=default
std::basic_string< char > operator()()
random_uniform_integer_t< size_t > m_wordcount_selector
random_uniform_integer_t< size_t > m_length_selector
random_words(size_t minimum, size_t maximum, size_t max_words, const Type(&alphabet)[ArraySize])
random_uniform_integer_t< size_t > m_character_selector
const CharType * m_alphabet
auto elapsed(bool bReset=true) const
std::string elapsed_time(bool bReset=true, TimeUnit dummy_time=TimeUnit{}) const
std::chrono::high_resolution_clock high_resolution_clock_t
auto random_generator(RangeType1 range_start, RangeType2 range_end)
duration_t< minute_t > minutes_t
duration_t< milli_t > milliseconds_t
random_words(int, int, int, const Type(&)[ArraySize]) -> random_words< Type, ArraySize >
duration_t< hour_t > hours_t
std::ratio< 3600 > hour_t
void random_parallel_fill(Type(&container)[N], const RandomGeneratorType< RType, RTypes... > &random_generator)
duration_t< micro_t > microseconds_t
std::chrono::duration< double, TimeUnit > duration_t
std::ratio< 60 > minute_t
double time_difference_in_unit(const time_point_t &start_time, const time_point_t &end_time)
std::default_random_engine random_engine_t
std::uniform_real_distribution< RealType > random_uniform_real_distribution
std::chrono::time_point< high_resolution_clock_t > time_point_t
unsigned int get_current_tick()
duration_t< nano_t > nanoseconds_t
std::uniform_int_distribution< IntegralType > random_uniform_integral_distribution
void random_fill(Type(&container)[N], RandomGeneratorType const &random_generator)
duration_t< second_t > seconds_t
std::string wstring_to_string(const std::wstring &wstr, unsigned int codepage=CP_UTF8)
Converts from std::wstring to std::string with codepage.
Includes subnamespace conversion.
auto minimum(Type_1 a, Type_2 b)
auto maximum(Type_1 a, Type_2 b)