From e2440bb2d455d06867fdae5e405fb8def752bda9 Mon Sep 17 00:00:00 2001
From: Tomas Pecka <peckato1@fit.cvut.cz>
Date: Fri, 8 Apr 2022 17:20:57 +0200
Subject: [PATCH] aux: add random number generator to CLI

I believe we need to push a random number generator algorithm to CLI in
order to write random tests using aql scripts.
---
 alib2aux/src/debug/Random.cpp      |  9 ---------
 alib2aux/src/debug/Random.h        | 19 -------------------
 alib2aux/src/generate/Random.cpp   | 11 +++++++++++
 alib2aux/src/generate/Random.h     | 28 ++++++++++++++++++++++++++++
 alib2std/src/extensions/random.hpp | 12 ++++++++++++
 5 files changed, 51 insertions(+), 28 deletions(-)
 delete mode 100644 alib2aux/src/debug/Random.cpp
 delete mode 100644 alib2aux/src/debug/Random.h
 create mode 100644 alib2aux/src/generate/Random.cpp
 create mode 100644 alib2aux/src/generate/Random.h

diff --git a/alib2aux/src/debug/Random.cpp b/alib2aux/src/debug/Random.cpp
deleted file mode 100644
index 33ccd78c1c..0000000000
--- a/alib2aux/src/debug/Random.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
-#include "Random.h"
-#include <registration/AlgoRegistration.hpp>
-
-namespace {
-
-auto RandomInt = registration::AbstractRegister < debug::Random < int >, int > ( debug::Random < int >::random );
-auto RandomUnsigned = registration::AbstractRegister < debug::Random < unsigned >, unsigned > ( debug::Random < unsigned >::random );
-
-} /* namespace */
diff --git a/alib2aux/src/debug/Random.h b/alib2aux/src/debug/Random.h
deleted file mode 100644
index a36240c68d..0000000000
--- a/alib2aux/src/debug/Random.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#pragma once
-
-#include <ext/random>
-
-namespace debug {
-
-template < class T >
-class Random {
-public:
-	static T random ( );
-};
-
-template < class T >
-T Random < T >::random ( ) {
-	return ext::random_devices::semirandom ( );
-}
-
-} /* namespace debug */
-
diff --git a/alib2aux/src/generate/Random.cpp b/alib2aux/src/generate/Random.cpp
new file mode 100644
index 0000000000..157e0ca957
--- /dev/null
+++ b/alib2aux/src/generate/Random.cpp
@@ -0,0 +1,11 @@
+#include "Random.h"
+#include <registration/AlgoRegistration.hpp>
+
+namespace {
+
+auto RandomInt = registration::AbstractRegister < generate::RandomFactory < int >, int > ( generate::RandomFactory < int >::randomNumber );
+auto RandomIntRange = registration::AbstractRegister < generate::RandomFactory < int >, int, const int&, const int& > ( generate::RandomFactory < int >::randomNumber );
+auto RandomUnsigned = registration::AbstractRegister < generate::RandomFactory < unsigned >, unsigned > ( generate::RandomFactory < unsigned >::randomNumber );
+auto RandomUnsignedRange = registration::AbstractRegister < generate::RandomFactory < unsigned >, unsigned, const unsigned&, const unsigned& > ( generate::RandomFactory < unsigned >::randomNumber );
+
+} /* namespace */
diff --git a/alib2aux/src/generate/Random.h b/alib2aux/src/generate/Random.h
new file mode 100644
index 0000000000..8c26d89924
--- /dev/null
+++ b/alib2aux/src/generate/Random.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include <ext/random>
+
+namespace generate {
+
+template < class T >
+class RandomFactory {
+public:
+	static T randomNumber ( );
+
+	/** @brief Returns random number within range lo (inclusive) and hi (exclusive) */
+	static T randomNumber ( const T& lo, const T& hi );
+};
+
+template < class T >
+T RandomFactory < T >::randomNumber ( ) {
+	return ext::random_devices::semirandom ( );
+}
+
+template < class T >
+T RandomFactory < T >::randomNumber ( const T& lo, const T& hi ) {
+
+	return ext::random_devices::semirandom ( lo, hi );
+}
+
+} /* namespace generate */
+
diff --git a/alib2std/src/extensions/random.hpp b/alib2std/src/extensions/random.hpp
index ebc7fa91df..6a4f496520 100644
--- a/alib2std/src/extensions/random.hpp
+++ b/alib2std/src/extensions/random.hpp
@@ -20,6 +20,7 @@
 
 #include <random>
 #include <limits>
+#include <stdexcept>
 
 namespace ext {
 
@@ -92,6 +93,17 @@ private:
 			return dis(gen);
 		}
 
+		/** \brief Returns random value withing lo (inclusive) and hi (exclusive)
+		 * \return semirandom value
+		 */
+		result_type operator()( const result_type& lo, const result_type& hi ) {
+			if ( lo >= hi ) {
+				throw std::invalid_argument ( "Empty range." );
+			}
+
+			return ( dis(gen) % ( hi - lo ) ) + lo;
+		}
+
 		/**
 		 * \brief
 		 * Getter of the minimal value the semirandom device can produce.
-- 
GitLab