diff --git a/source/framework/tools/inc/TRestTools.h b/source/framework/tools/inc/TRestTools.h index 58836b4bf..5ce2e2aac 100644 --- a/source/framework/tools/inc/TRestTools.h +++ b/source/framework/tools/inc/TRestTools.h @@ -131,6 +131,8 @@ class TRestTools { static std::string POSTRequest(const std::string& url, const std::map& keys); static void ChangeDirectory(const std::string& toDirectory); + + static std::vector CanvasDivisions(int n); }; namespace REST_InitTools { diff --git a/source/framework/tools/src/TRestTools.cxx b/source/framework/tools/src/TRestTools.cxx index 0af3237fa..9b8f3a458 100644 --- a/source/framework/tools/src/TRestTools.cxx +++ b/source/framework/tools/src/TRestTools.cxx @@ -1249,6 +1249,58 @@ int TRestTools::UploadToServer(string localFile, string remoteFile, string metho void TRestTools::ChangeDirectory(const string& toDirectory) { filesystem::current_path(toDirectory); } +/////////////////////////////////////////////// +/// \brief It returns a vector with 2 components {a,b}, the components satisfy that `a x b = n`, +/// being the ratio a/b as close to 1 as possible. +/// +/// This method can be used to help dividing a canvas that will contain a number `n` of plots. +/// +/// If `n` is a prime number, then the pair generated will be `n x 1`. +/// +std::vector TRestTools::CanvasDivisions(int n) { + std::vector r; + for (int i = 2; i * i <= n; i += 1 + (i > 2)) { + while ((n % i) == 0) { + r.push_back(i); + n /= i; + } + } + if (n != 1) r.push_back(n); + + while (r.size() > 2) { + // We multiply the 2 lowest elements and + // replace the elements in the vector by the result + auto min1 = std::min_element(r.begin(), r.end()); + int low1 = *min1; + + // Remove the first element equal to min1 (efficient way) + auto it = std::find(r.begin(), r.end(), low1); + if (it != r.end()) { + std::iter_swap(it, r.end() - 1); + r.erase(r.end() - 1); + } + + auto min2 = std::min_element(r.begin(), r.end()); + int low2 = *min2; + + // Remove the first element equal to min2 (efficient way) + it = std::find(r.begin(), r.end(), low2); + if (it != r.end()) { + std::iter_swap(it, r.end() - 1); + r.erase(r.end() - 1); + } + + int resultado = low1 * low2; + r.push_back(resultado); + } + + std::sort(r.begin(), r.end()); + + if (r.size() == 1) r.push_back(1); + + return r; +} + string ValueWithQuantity::ToString() const { string unit; auto value = fValue;