OPAL (Object Oriented Parallel Accelerator Library) 2024.2
OPAL
Util.cpp
Go to the documentation of this file.
1//
2// Namespace Util
3// This namespace contains useful global methods.
4//
5// Copyright (c) 200x - 2022, Paul Scherrer Institut, Villigen PSI, Switzerland
6// All rights reserved
7//
8// This file is part of OPAL.
9//
10// OPAL is free software: you can redistribute it and/or modify
11// it under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// You should have received a copy of the GNU General Public License
16// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
17//
18#include "Utilities/Util.h"
19
20#include "OPALrevision.h"
22
23#include <algorithm>
24#include <cctype>
25#include <cmath>
26#include <filesystem>
27#include <fstream>
28#include <iostream>
29#include <queue>
30#include <regex>
31#include <sstream>
32#include <string>
33#include <vector>
34
35#include <zlib.h>
36
37namespace Util {
38 std::string getGitRevision() {
39 return std::string(GIT_VERSION);
40 }
41
42#define erfinv_a3 -0.140543331
43#define erfinv_a2 0.914624893
44#define erfinv_a1 -1.645349621
45#define erfinv_a0 0.886226899
46
47#define erfinv_b4 0.012229801
48#define erfinv_b3 -0.329097515
49#define erfinv_b2 1.442710462
50#define erfinv_b1 -2.118377725
51#define erfinv_b0 1
52
53#define erfinv_c3 1.641345311
54#define erfinv_c2 3.429567803
55#define erfinv_c1 -1.62490649
56#define erfinv_c0 -1.970840454
57
58#define erfinv_d2 1.637067800
59#define erfinv_d1 3.543889200
60#define erfinv_d0 1
61
62 double erfinv (double x) // inverse error function
63 {
64 double r;
65 int sign_x;
66
67 if (x < -1 || x > 1)
68 return NAN;
69
70 if (x == 0)
71 return 0;
72
73 if (x > 0)
74 sign_x = 1;
75 else {
76 sign_x = -1;
77 x = -x;
78 }
79
80 if (x <= 0.7) {
81 double x2 = x * x;
82 r =
83 x * (((erfinv_a3 * x2 + erfinv_a2) * x2 + erfinv_a1) * x2 + erfinv_a0);
84 r /= (((erfinv_b4 * x2 + erfinv_b3) * x2 + erfinv_b2) * x2 +
85 erfinv_b1) * x2 + erfinv_b0;
86 }
87 else {
88 double y = std::sqrt (-std::log ((1 - x) / 2));
89 r = (((erfinv_c3 * y + erfinv_c2) * y + erfinv_c1) * y + erfinv_c0);
90 r /= ((erfinv_d2 * y + erfinv_d1) * y + erfinv_d0);
91 }
92
93 r = r * sign_x;
94 x = x * sign_x;
95
96 r -= (std::erf (r) - x) / (2 / std::sqrt (Physics::pi) * std::exp (-r * r));
97 r -= (std::erf (r) - x) / (2 / std::sqrt (Physics::pi) * std::exp (-r * r));
98
99 return r;
100 }
101
102#undef erfinv_a3
103#undef erfinv_a2
104#undef erfinv_a1
105#undef erfinv_a0
106
107#undef erfinv_b4
108#undef erfinv_b3
109#undef erfinv_b2
110#undef erfinv_b1
111#undef erfinv_b0
112
113#undef erfinv_c3
114#undef erfinv_c2
115#undef erfinv_c1
116#undef erfinv_c0
117
118#undef erfinv_d2
119#undef erfinv_d1
120#undef erfinv_d0
121
122 Vector_t getTaitBryantAngles(Quaternion rotation, const std::string& /*elementName*/) {
123 Quaternion rotationBAK = rotation;
124
125 // y axis
126 Vector_t tmp = rotation.rotate(Vector_t({0, 0, 1}));
127 tmp(1) = 0.0;
128 // tmp /= euclidean_norm(tmp);
129 double theta = std::fmod(std::atan2(tmp(0), tmp(2)) + Physics::two_pi, Physics::two_pi);
130
131 Quaternion rotTheta(std::cos(0.5 * theta), 0, std::sin(0.5 * theta), 0);
132 rotation = rotTheta.conjugate() * rotation;
133
134 // x axis
135 tmp = rotation.rotate(Vector_t({0, 0, 1}));
136 tmp(0) = 0.0;
137 tmp /= euclidean_norm(tmp);
138 double phi = std::fmod(std::atan2(-tmp(1), tmp(2)) + Physics::two_pi, Physics::two_pi);
139
140 Quaternion rotPhi(std::cos(0.5 * phi), std::sin(0.5 * phi), 0, 0);
141 rotation = rotPhi.conjugate() * rotation;
142
143 // z axis
144 tmp = rotation.rotate(Vector_t({1, 0, 0}));
145 tmp(2) = 0.0;
146 tmp /= euclidean_norm(tmp);
147 double psi = std::fmod(std::atan2(tmp(1), tmp(0)) + Physics::two_pi, Physics::two_pi);
148
149 return Vector_t({theta, phi, psi});
150 }
151
152 std::string toUpper(const std::string& str) {
153 std::string output = str;
154 std::transform(output.begin(), output.end(), output.begin(),
155 [](unsigned char c) {
156 return std::toupper(c);
157 });
158 return output;
159 }
160
161 std::string boolToUpperString(const bool& b) {
162 std::ostringstream valueStream;
163 valueStream << std::boolalpha << b;
164 std::string output = Util::toUpper(valueStream.str());
165 return output;
166 }
167
168 std::string boolVectorToUpperString(const std::vector<bool>& b) {
169 std::ostringstream output;
170 if (b.size() > 1) {
171 output << "(";
172 }
173 for (std::size_t i = 0; i < b.size(); ++i) {
174 output << std::boolalpha << boolToUpperString(b[i]);
175 if (b.size() > 1) {
176 (i < (b.size()-1)) ? (output << ", ") : (output << ")");
177 }
178 }
179
180 return output.str();
181 }
182
183 std::string doubleVectorToString(const std::vector<double>& v) {
184 std::vector<std::string> stringVec;
185 stringVec.reserve(v.size());
186 Util::toString(std::begin(v), std::end(v), std::back_inserter(stringVec));
187
188 std::ostringstream output;
189 if (v.size() > 1) {
190 output << "(";
191 }
192 unsigned int i = 0;
193 for (auto& s: stringVec) {
194 ++i;
195 output << s;
196 if (v.size() > 1) {
197 (i < stringVec.size()) ? (output << ", ") : (output << ")");
198 }
199 }
200
201 return output.str();
202 }
203
204 std::string combineFilePath(std::initializer_list<std::string> ilist) {
205 std::filesystem::path path;
206 for (auto entry : ilist) {
207 path /= entry;
208 }
209 return path.string();
210 }
211
212 void checkInt(double real, const std::string& name, double tolerance) {
213 real += tolerance; // prevent rounding error
214 if (std::abs(std::floor(real) - real) > 2*tolerance) {
215 throw OpalException("Util::checkInt",
216 "Value for " + name +
217 " should be an integer but a real value was found");
218 }
219 if (std::floor(real) < 0.5) {
220 throw OpalException("Util::checkInt",
221 "Value for " + name + " should be 1 or more");
222 }
223 }
224
225 bool isAllDigits(const std::string& str) {
226 return std::all_of(str.begin(),
227 str.end(),
228 [](char c) { return std::isdigit(c); });
229 }
230
231 std::string replaceAll(const std::string& str,
232 const std::string& from,
233 const std::string& to) {
234 if (from.empty()) return str;
235
236 std::string result;
237 result.reserve(str.size());
238
239 std::size_t pos = 0, found;
240 while ((found = str.find(from, pos)) != std::string::npos) {
241 result.append(str, pos, found - pos);
242 result += to;
243 pos = found + from.length();
244 }
245 result.append(str, pos, std::string::npos);
246
247 return result;
248 }
249
250 std::vector<std::string> split_any_of(const std::string& s,
251 const std::string& delims,
252 bool compress) {
253 std::vector<std::string> out;
254 std::string token;
255 for (char c : s) {
256 if (delims.find(c) != std::string::npos) {
257 if (!token.empty() || !compress) {
258 out.push_back(token);
259 }
260 token.clear();
261 } else {
262 token.push_back(c);
263 }
264 }
265 if (!token.empty() || !compress) {
266 out.push_back(token);
267 }
268 return out;
269 }
270
271 std::string compressString(const std::string& str) {
272 if (str.empty()) return {};
273
274 uLongf compressed_size = compressBound(str.size());
275 std::string out(compressed_size, '\0');
276
277 int ret = compress2(reinterpret_cast<Bytef*>(&out[0]), &compressed_size,
278 reinterpret_cast<const Bytef*>(str.data()),
279 str.size(), Z_BEST_COMPRESSION);
280
281 if (ret != Z_OK) {
282 throw std::runtime_error("zlib compression failed");
283 }
284
285 out.resize(compressed_size);
286 return out;
287 }
288
290 sum(0.0),
291 correction(0.0)
292 { }
293
295 long double y = value - this->correction;
296 long double t = this->sum + y;
297 this->correction = (t - this->sum) - y;
298 this->sum = t;
299 return *this;
300 }
301
305 unsigned int rewindLinesSDDS(const std::string& fileName, double maxSPos, bool checkForTime) {
306 if (Ippl::myNode() > 0) return 0;
307
308 std::fstream fs(fileName.c_str(), std::fstream::in);
309 if (!fs.is_open()) return 0;
310
311 std::string line;
312 std::queue<std::string> allLines;
313 unsigned int numParameters = 0;
314 unsigned int numColumns = 0;
315 unsigned int sposColumnNr = 0;
316 unsigned int timeColumnNr = 0;
317 double spos, time = 0.0;
318 double lastTime = -1.0;
319
320 std::regex parameters("&parameter");
321 std::regex column("&column");
322 std::regex data("&data");
323 std::regex end("&end");
324 std::regex name("name=([a-zA-Z0-9\\$_]+)");
325 std::smatch match;
326
327 std::istringstream linestream;
328
329 while (std::getline(fs, line)) {
330 allLines.push(line);
331 }
332 fs.close();
333
334 fs.open (fileName.c_str(), std::fstream::out);
335
336 if (!fs.is_open()) return 0;
337
338 do {
339 line = allLines.front();
340 allLines.pop();
341 fs << line << "\n";
342 if (std::regex_search(line, match, parameters)) {
343 ++numParameters;
344 while (!std::regex_search(line, match, end)) {
345 line = allLines.front();
346 allLines.pop();
347 fs << line << "\n";
348 }
349 } else if (std::regex_search(line, match, column)) {
350 ++numColumns;
351 while (!std::regex_search(line, match, name)) {
352 line = allLines.front();
353 allLines.pop();
354 fs << line << "\n";
355 }
356 if (match[1] == "s") {
357 sposColumnNr = numColumns;
358 }
359 if (match[1] == "t") {
360 timeColumnNr = numColumns;
361 }
362 while (!std::regex_search(line, match, end)) {
363 line = allLines.front();
364 allLines.pop();
365 fs << line << "\n";
366 }
367 }
368 } while (!std::regex_search(line, match, data));
369
370 while (!std::regex_search(line, match, end)) {
371 line = allLines.front();
372 allLines.pop();
373 fs << line << "\n";
374 }
375
376 for (unsigned int i = 0; i < numParameters; ++ i) {
377 fs << allLines.front() << "\n";
378 allLines.pop();
379 }
380
381 while (!allLines.empty()) {
382 line = allLines.front();
383
384 linestream.str(line);
385 if (checkForTime) {
386 for (unsigned int i = 0; i < timeColumnNr; ++ i) {
387 linestream >> time;
388 }
389 }
390
391 linestream.str(line);
392 for (unsigned int i = 0; i < sposColumnNr; ++ i) {
393 linestream >> spos;
394 }
395
396 if ((spos - maxSPos) > 1e-20 * Physics::c) break;
397
398 allLines.pop();
399
400 if (!checkForTime || (time - lastTime) > 1e-20)
401 fs << line << "\n";
402
403 lastTime = time;
404 }
405
406 fs.close();
407
408 if (!allLines.empty())
409 INFOMSG(level2 << "rewind " + fileName + " to " + std::to_string(maxSPos) << " m" << endl);
410
411 return allLines.size();
412 }
413
414 /*
415 base64.cpp and base64.h
416
417 Copyright (C) 2004-2008 René Nyffenegger
418
419 This source code is provided 'as-is', without any express or implied
420 warranty. In no event will the author be held liable for any damages
421 arising from the use of this software.
422
423 Permission is granted to anyone to use this software for any purpose,
424 including commercial applications, and to alter it and redistribute it
425 freely, subject to the following restrictions:
426
427 1. The origin of this source code must not be misrepresented; you must not
428 claim that you wrote the original source code. If you use this source code
429 in a product, an acknowledgment in the product documentation would be
430 appreciated but is not required.
431
432 2. Altered source versions must be plainly marked as such, and must not be
433 misrepresented as being the original source code.
434
435 3. This notice may not be removed or altered from any source distribution.
436
437 René Nyffenegger rene.nyffenegger@adp-gmbh.ch
438
439 */
440
441 static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
442 "abcdefghijklmnopqrstuvwxyz"
443 "0123456789+/";
444
445 static inline bool is_base64(unsigned char c) {
446 return (std::isalnum(c) || (c == '+') || (c == '/'));
447 }
448
449 std::string base64_encode(const std::string& string_to_encode) {
450 const char* bytes_to_encode = string_to_encode.c_str();
451 unsigned int in_len = string_to_encode.size();
452 std::string ret;
453 int i = 0;
454 int j = 0;
455 unsigned char char_array_3[3];
456 unsigned char char_array_4[4];
457
458 while (in_len--) {
459 char_array_3[i++] = *(bytes_to_encode++);
460 if (i == 3) {
461 char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
462 char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
463 char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
464 char_array_4[3] = char_array_3[2] & 0x3f;
465
466 for (i = 0; (i <4) ; i++)
467 ret += base64_chars[char_array_4[i]];
468 i = 0;
469 }
470 }
471
472 if (i)
473 {
474 for (j = i; j < 3; j++)
475 char_array_3[j] = '\0';
476
477 char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
478 char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
479 char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
480 char_array_4[3] = char_array_3[2] & 0x3f;
481
482 for (j = 0; (j < i + 1); j++)
483 ret += base64_chars[char_array_4[j]];
484
485 while((i++ < 3))
486 ret += '=';
487
488 }
489
490 return ret;
491 }
492
493 std::string base64_decode(std::string const& encoded_string) {
494 int in_len = encoded_string.size();
495 int i = 0;
496 int j = 0;
497 int in_ = 0;
498 unsigned char char_array_4[4], char_array_3[3];
499 std::string ret;
500
501 while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
502 char_array_4[i++] = encoded_string[in_]; in_++;
503 if (i ==4) {
504 for (i = 0; i <4; i++)
505 char_array_4[i] = base64_chars.find(char_array_4[i]);
506
507 char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
508 char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
509 char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
510
511 for (i = 0; (i < 3); i++)
512 ret += char_array_3[i];
513 i = 0;
514 }
515 }
516
517 if (i) {
518 for (j = i; j <4; j++)
519 char_array_4[j] = 0;
520
521 for (j = 0; j <4; j++)
522 char_array_4[j] = base64_chars.find(char_array_4[j]);
523
524 char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
525 char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
526 char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
527
528 for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
529 }
530
531 return ret;
532 }
533}
PartBunchBase< T, Dim >::ConstIterator end(PartBunchBase< T, Dim > const &bunch)
FLieGenerator< T, N > real(const FLieGenerator< std::complex< T >, N > &)
Take real part of a complex generator.
#define erfinv_c1
Definition Util.cpp:55
#define erfinv_d0
Definition Util.cpp:60
#define erfinv_a0
Definition Util.cpp:45
#define erfinv_b2
Definition Util.cpp:49
#define erfinv_b1
Definition Util.cpp:50
#define erfinv_a2
Definition Util.cpp:43
#define erfinv_c2
Definition Util.cpp:54
#define erfinv_c3
Definition Util.cpp:53
#define erfinv_d1
Definition Util.cpp:59
#define erfinv_a1
Definition Util.cpp:44
#define erfinv_a3
Definition Util.cpp:42
#define erfinv_b4
Definition Util.cpp:47
#define erfinv_d2
Definition Util.cpp:58
#define erfinv_b0
Definition Util.cpp:51
#define erfinv_b3
Definition Util.cpp:48
#define erfinv_c0
Definition Util.cpp:56
T euclidean_norm(const Vector< T > &)
Euclidean norm.
Definition Vector.h:243
#define INFOMSG(msg)
Definition IpplInfo.h:348
Inform & level2(Inform &inf)
Definition Inform.cpp:46
Inform & endl(Inform &inf)
Definition Inform.cpp:42
T::PETE_Expr_t::PETE_Return_t sum(const PETE_Expr< T > &expr)
Definition PETE.h:1111
const std::string name
constexpr double two_pi
The value of.
Definition Physics.h:33
constexpr double c
The velocity of light in m/s.
Definition Physics.h:45
constexpr double pi
The value of.
Definition Physics.h:30
Definition Util.cpp:37
void checkInt(double real, const std::string &name, double tolerance)
Definition Util.cpp:212
std::string combineFilePath(std::initializer_list< std::string > ilist)
Definition Util.cpp:204
std::string doubleVectorToString(const std::vector< double > &v)
Definition Util.cpp:183
Vector_t getTaitBryantAngles(Quaternion rotation, const std::string &)
Definition Util.cpp:122
std::string boolVectorToUpperString(const std::vector< bool > &b)
Definition Util.cpp:168
void toString(IteratorIn first, IteratorIn last, IteratorOut out)
Definition Util.h:358
std::string toUpper(const std::string &str)
Definition Util.cpp:152
double erfinv(double x)
Definition Util.cpp:62
std::vector< std::string > split_any_of(const std::string &s, const std::string &delims, bool compress)
Definition Util.cpp:250
std::string base64_decode(std::string const &encoded_string)
Definition Util.cpp:493
std::string replaceAll(const std::string &str, const std::string &from, const std::string &to)
Definition Util.cpp:231
unsigned int rewindLinesSDDS(const std::string &fileName, double maxSPos, bool checkForTime)
rewind the SDDS file such that the spos of the last step is less or equal to maxSPos
Definition Util.cpp:305
std::string getGitRevision()
Definition Util.cpp:38
std::string compressString(const std::string &str)
Definition Util.cpp:271
std::string base64_encode(const std::string &string_to_encode)
Definition Util.cpp:449
std::string boolToUpperString(const bool &b)
Definition Util.cpp:161
bool isAllDigits(const std::string &str)
Definition Util.cpp:225
Vector_t rotate(const Vector_t &) const
Quaternion conjugate() const
Definition Quaternion.h:103
long double sum
Definition Util.h:304
long double correction
Definition Util.h:305
KahanAccumulation & operator+=(double value)
Definition Util.cpp:294
The base class for all OPAL exceptions.
static int myNode()
Definition IpplInfo.cpp:691
Vektor< double, 3 > Vector_t
Definition Vektor.h:6