GammaLib 2.0.0
Loading...
Searching...
No Matches
GIntegrals.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * GIntegrals.cpp - Integration class for set of functions *
3 * ----------------------------------------------------------------------- *
4 * copyright (C) 2020 by Juergen Knoedlseder *
5 * ----------------------------------------------------------------------- *
6 * *
7 * This program is free software: you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation, either version 3 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
19 * *
20 ***************************************************************************/
21/**
22 * @file GIntegrals.cpp
23 * @brief Integration class for set of functions implementation
24 * @author Juergen Knoedlseder
25 */
26
27/* __ Includes ___________________________________________________________ */
28#include <cmath> // std::abs()
29#include <vector>
30#include <algorithm> // std::sort
31#include "GIntegrals.hpp"
32#include "GException.hpp"
33#include "GTools.hpp"
34#include "GFunctions.hpp"
35
36/* __ Method name definitions ____________________________________________ */
37#define G_ROMBERG1 "GIntegrals::romberg(std::vector<double>, int&)"
38#define G_ROMBERG2 "GIntegrals::romberg(double&, double&, int&)"
39#define G_GAUSS_KRONROD "GIntegrals::gauss_kronrod(double&, double&)"
40#define G_TRAPZD "GIntegrals::trapzd(double&, double&, int&, GVector)"
41#define G_POLINT "GIntegrals::polint(double*, GVector*, int, int, double, "\
42 "GVector*)"
43
44/* __ Macros _____________________________________________________________ */
45
46/* __ Coding definitions _________________________________________________ */
47
48/* __ Debug definitions __________________________________________________ */
49
50/* __ Constants __________________________________________________________ */
51
52
53/*==========================================================================
54 = =
55 = Constructors/destructors =
56 = =
57 ==========================================================================*/
58
59/***********************************************************************//**
60 * @brief Void constructor
61 ***************************************************************************/
63{
64 // Initialise members
66
67 // Return
68 return;
69}
70
71
72/***********************************************************************//**
73 * @brief Vector function kernels constructor
74 *
75 * @param[in] kernels Pointer to function kernels.
76 *
77 * The vector function kernels constructor assigns the vector function
78 * kernels pointer in constructing the object.
79 ***************************************************************************/
81{
82 // Initialise members
84
85 // Set function kernel
87
88 // Return
89 return;
90}
91
92
93/***********************************************************************//**
94 * @brief Copy constructor
95 *
96 * @param[in] integrals Integrals.
97 ***************************************************************************/
99{
100 // Initialise members
101 init_members();
102
103 // Copy members
104 copy_members(integrals);
105
106 // Return
107 return;
108}
109
110
111/***********************************************************************//**
112 * @brief Destructor
113 ***************************************************************************/
115{
116 // Free members
117 free_members();
118
119 // Return
120 return;
121}
122
123
124/*==========================================================================
125 = =
126 = Operators =
127 = =
128 ==========================================================================*/
129
130/***********************************************************************//**
131 * @brief Assignment operator
132 *
133 * @param[in] integrals Integrals.
134 * @return Integrals.
135 ***************************************************************************/
137{
138 // Execute only if object is not identical
139 if (this != &integrals) {
140
141 // Free members
142 free_members();
143
144 // Initialise integral
145 init_members();
146
147 // Copy members
148 copy_members(integrals);
149
150 } // endif: object was not identical
151
152 // Return
153 return *this;
154}
155
156
157/*==========================================================================
158 = =
159 = Public methods =
160 = =
161 ==========================================================================*/
162
163/***********************************************************************//**
164 * @brief Clear integral
165 ***************************************************************************/
167{
168 // Free members
169 free_members();
170
171 // Initialise private members
172 init_members();
173
174 // Return
175 return;
176}
177
178
179/***********************************************************************//**
180 * @brief Clone integral
181 *
182 * @return Pointer to deep copy of integrals.
183 ***************************************************************************/
185{
186 return new GIntegrals(*this);
187}
188
189
190/***********************************************************************//**
191 * @brief Perform Romberg integration
192 *
193 * @param[in] bounds Integration boundaries.
194 * @param[in] order Integration order (default: 5)
195 * @return Vector of integration results.
196 *
197 * Returns the integral of the integrand, computed over a number of
198 * intervals [a0,a1], [a1,a2], ... that are given as an unordered vector
199 * by the @p bounds argument.
200 *
201 * Integration is performed by Romberg's method of order 2*order, where
202 *
203 * order=1 is equivalent to the trapezoidal rule,
204 * order=2 is equivalent to Simpson's rule, and
205 * order=3 is equivalent to Boole's rule.
206 *
207 * The number of iterations is limited by m_max_iter. m_eps specifies the
208 * requested fractional accuracy. By default it is set to 1e-6.
209 ***************************************************************************/
210GVector GIntegrals::romberg(std::vector<double> bounds, const int& order)
211{
212 // Throw an exception if the instance has no kernels
213 if (m_kernels == NULL) {
214 std::string msg = "Function kernels not set. Please set function "
215 "kernels before calling the method.";
217 }
218
219 // Sort integration boundaries in ascending order
220 std::sort(bounds.begin(), bounds.end());
221
222 // Initialise result
223 GVector result(m_kernels->size());
224
225 // Initialise integration status information
226 int calls = 0;
227
228 // Add integral of all intervals
229 for (int i = 0; i < bounds.size()-1; ++i) {
230 result += romberg(bounds[i], bounds[i+1], order);
231 calls += m_calls;
232 }
233
234 // Set integration status information
235 m_calls = calls;
236
237 // Return result
238 return result;
239}
240
241
242/***********************************************************************//**
243 * @brief Perform Romberg integration
244 *
245 * @param[in] a Left integration boundary.
246 * @param[in] b Right integration boundary.
247 * @param[in] order Integration order (default: 5)
248 * @return Vector of integration results.
249 *
250 * @exception GException::invalid_value
251 * Function kernels not set.
252 * @exception GException::invalid_argument
253 * Integration order incompatible with number of iterations.
254 *
255 * Returns the integral of the integrand from a to b. Integration is
256 * performed by Romberg's method of order 2*order, where
257 *
258 * order=1 is equivalent to the trapezoidal rule,
259 * order=2 is equivalent to Simpson's rule, and
260 * order=3 is equivalent to Boole's rule.
261 *
262 * The number of iterations is limited by m_max_iter. m_eps specifies the
263 * requested fractional accuracy. By default it is set to 1e-6.
264 ***************************************************************************/
265GVector GIntegrals::romberg(const double& a, const double& b, const int& order)
266{
267 // Throw an exception if the instance has no kernels
268 if (m_kernels == NULL) {
269 std::string msg = "Function kernels not set. Please set function "
270 "kernels before calling the method.";
272 }
273
274 // Initialise result
275 GVector result(m_kernels->size());
276
277 // Initialise integration status information
278 m_isvalid = true;
279 m_calls = 0;
280 m_has_abserr = false;
281 m_has_relerr = false;
282
283 // Continue only if integration range is valid
284 if (b > a) {
285
286 // Initialise variables
287 bool converged = false;
288 GVector dss(m_kernels->size());
289
290 // Determine (maximum) number of iterations
292
293 // Check whether maximum number of iterations is compliant with
294 // order
295 if (order > max_iter) {
296 std::string msg = "Requested integration order "+
297 gammalib::str(order)+" is larger than the "
298 "maximum number of iterations "+
299 gammalib::str(max_iter)+". Either reduce the "
300 "integration order or increase the (maximum) "
301 "number of iterations.";
303 }
304
305 // Allocate temporal storage
306 double* h = new double[max_iter+2];
307 GVector* s = new GVector[max_iter+2];
308
309 // Initialise step size and initial result
310 h[1] = 1.0;
311 s[0] = GVector(m_kernels->size());
312
313 // Iterative loop
314 for (m_iter = 1; m_iter <= max_iter; ++m_iter) {
315
316 // Integration using Trapezoid rule
317 s[m_iter] = trapzd(a, b, m_iter, s[m_iter-1]);
318
319 // Compile option: Check for NaN/Inf
320 #if defined(G_NAN_CHECK)
321 if (is_notanumber(s[m_iter]) || is_infinite(s[m_iter])) {
322 m_message = "*** ERROR: GIntegrals::romberg"
323 "(a="+gammalib::str(a)+", b="+gammalib::str(b)+""
324 ", k="+gammalib::str(k)+"): NaN/Inf encountered"
325 " (s["+gammalib::str(m_iter)+"]="
326 ""+s[m_iter]->print()+")";
327 std::cout << m_message << std::endl;
328 m_isvalid = false;
329 }
330 #endif
331
332 // Starting from iteration order on, use polynomial interpolation
333 if (m_iter >= order) {
334
335 // Compute result using polynom interpolation
336 result = polint(&h[m_iter-order], &s[m_iter-order], order, 0.0, &dss);
337
338 // If a fixed number of iterations has been requested and if
339 // the final iteration was reached then set the converged
340 // flag
341 if (m_fix_iter > 0) {
342 if (m_iter == max_iter) {
343 converged = true;
344 }
345 }
346
347 // ... otherwise if the requested precision was reached for
348 // all functions then set the converged flag
349 else {
350 converged = true;
351 for (int i = 0; i < result.size(); ++i) {
352 if (std::abs(dss[i]) > m_eps * std::abs(result[i])) {
353 converged = false;
354 break;
355 }
356 }
357 }
358
359 // If the integration has converged then compute the absolute
360 // and the relative integration errors. If an intergation result
361 // is zero, the relative error is set to zero. The relative
362 // error flag is set to true if at least one of the relative
363 // integration errors is valid.
364 if (converged) {
365 m_has_abserr = true;
366 m_abserr = abs(dss);
368 for (int i = 0; i < result.size(); ++i) {
369 double abs_result = std::abs(result[i]);
370 if (abs_result > 0.0) {
371 m_relerr[i] /= abs_result;
372 m_has_relerr = true;
373 }
374 else {
375 m_relerr[i] = 0.0;
376 }
377 }
378 break;
379 }
380
381 } // endif: polynomial interpolation performed
382
383 // Reduce step size
384 h[m_iter+1] = 0.25 * h[m_iter];
385
386 } // endfor: iterative loop
387
388 // Delete temporal storage
389 delete [] s;
390 delete [] h;
391
392 // Set status and optionally dump warning
393 if (!converged) {
394 m_isvalid = false;
395 m_message = "Integration uncertainty "+(abs(dss)).print()+
396 " exceeds absolute tolerance of "+
397 (m_eps * abs(result)).print()+
398 " after "+gammalib::str(m_iter)+" iterations. Result "+
399 result.print()+" is inaccurate.";
400 if (!m_silent) {
401 std::string origin = "GIntegrals::romberg("+
402 gammalib::str(a)+", "+
403 gammalib::str(b)+", "+
404 gammalib::str(order)+")";
406 }
407 }
408
409 } // endif: integration range was valid
410
411 // Return result
412 return result;
413}
414
415
416/***********************************************************************//**
417 * @brief Perform Trapezoidal integration for a set of functions
418 *
419 * @param[in] a Left integration boundary.
420 * @param[in] b Right integration boundary.
421 * @param[in] n Number of steps.
422 * @param[in] previous_result Result vector from a previous trapezoidal
423 * integration step.
424 * @return Vector of integration results.
425 *
426 * @exception GException::invalid_value
427 * Function kernels not set.
428 *
429 * The method performs a trapezoidal integration of a set of functions for
430 * the integration interval [a,b].
431 *
432 * If @p n = 1 the integral for each function \f$j\f$ is computed using
433 *
434 * \f[
435 * \int_a^b f_j(x) \, dx = \frac{1}{2} (b-a) (f_j(a) + f_j(b))
436 * \f]
437 *
438 * For @p n > 1 the integral is computed using
439 *
440 * \f[
441 * \int_a^b f_j(x) \, dx = \frac{1}{2} \left[{\tt previous\_result}_j +
442 * \frac{b-a}{2^{n-1}}
443 * \sum_{i=0}^{2^{n-1}-1} f_j \left( a + (0.5+i) \frac{b-a}{2^{n-1}}
444 * \right) \right]
445 * \f]
446 *
447 * where \f${\tt previous\_result}_j\f$ is the integration result for
448 * function \f$j\f$ from a previous call to the method with @p n = @p n - 1.
449 ***************************************************************************/
451 const double& b,
452 const int& n,
453 const GVector& previous_result)
454{
455 // Throw an exception if the instance has no kernel
456 if (m_kernels == NULL) {
457 std::string msg = "Function kernels not set. Please set function "
458 "kernels before calling the method.";
460 }
461
462 // If lower boundary is smaller than upper boundary than use trapezoidal
463 // rule
464 if (a < b) {
465
466 // Case A: Only a single step is requested
467 if (n == 1) {
468
469 // Evaluate integrand at boundaries
470 GVector result = 0.5 * (b-a) * (m_kernels->eval(a) +
471 m_kernels->eval(b));
472
473 // Bookkeeping of function calls
474 m_calls += 2;
475
476 // Return result here to avoid an extra vector copy
477 return result;
478
479 } // endif: only a single step was requested
480
481 // Case B: More than a single step is requested
482 else {
483
484 // Compute step level 2^(n-1)
485 int it = 1;
486 for (int j = 1; j < n-1; ++j) {
487 it <<= 1;
488 }
489
490 // Verify that step level is valid
491 if (it == 0) {
492 m_isvalid = false;
493 m_message = "Invalid step level "+gammalib::str(it)+
494 " encountered for"
495 " a="+gammalib::str(a)+
496 ", b="+gammalib::str(b)+
497 ", n="+gammalib::str(n)+
498 ", result="+previous_result.print()+
499 ". Looks like n is too large.";
500 if (!m_silent) {
502 }
503 }
504
505 // Set step size
506 double tnm = double(it);
507 double del = (b-a)/tnm;
508
509 // Verify that step is >0
510 if (del == 0) {
511 m_isvalid = false;
512 m_message = "Invalid step size "+gammalib::str(del)+
513 " encountered for"
514 " a="+gammalib::str(a)+
515 ", b="+gammalib::str(b)+
516 ", n="+gammalib::str(n)+
517 ", result="+previous_result.print()+
518 ". Step is too small to make sense.";
519 if (!m_silent) {
521 }
522 }
523
524 // Initialise result
525 GVector result(previous_result.size());
526
527 // Initialise argument
528 double x = a + 0.5 * del;
529
530 // Sum up values
531 for (int j = 0; j < it; ++j, x += del) {
532
533 // Evaluate and add integrand
534 result += m_kernels->eval(x);
535
536 // Bookkeeping of function calls
537 m_calls++;
538
539 } // endfor: looped over steps
540
541 // Compute result benefiting from previous result
542 result *= del;
543 result += previous_result;
544 result *= 0.5;
545
546 // Return result here to avoid an extra vector copy
547 return result;
548
549 } // endelse: Case B
550
551 } // endif: trapezoidal rule was applied
552
553 // ... otherwise handle case a >= b
554 else {
555
556 // Set empty vector
557 GVector result(previous_result.size());
558
559 // Return result here to avoid an extra vector copy
560 return result;
561 }
562
563}
564
565
566/***********************************************************************//**
567 * @brief Print integral information
568 *
569 * @param[in] chatter Chattiness.
570 * @return String containing integral information.
571 ***************************************************************************/
572std::string GIntegrals::print(const GChatter& chatter) const
573{
574 // Initialise result string
575 std::string result;
576
577 // Continue only if chatter is not silent
578 if (chatter != SILENT) {
579
580 // Append header
581 result.append("=== GIntegrals ===");
582
583 // Append information
584 result.append("\n"+gammalib::parformat("Relative precision"));
585 result.append(gammalib::str(eps()));
586 if (m_has_abserr) {
587 result.append("\n"+gammalib::parformat("Absolute errors"));
588 result.append(m_abserr.print());
589 }
590 if (m_has_relerr) {
591 result.append("\n"+gammalib::parformat("Relative errors"));
592 result.append(m_relerr.print());
593 }
594 result.append("\n"+gammalib::parformat("Function calls"));
595 result.append(gammalib::str(calls()));
596 result.append("\n"+gammalib::parformat("Iterations"));
597 result.append(gammalib::str(iter()));
598 if (m_fix_iter > 0) {
599 result.append(" (fixed: ");
600 result.append(gammalib::str(fixed_iter()));
601 result.append(")");
602 }
603 else {
604 result.append(" (maximum: ");
605 result.append(gammalib::str(max_iter()));
606 result.append(")");
607 }
608
609 // Append status information
610 result.append("\n"+gammalib::parformat("Status"));
611 if (is_valid()) {
612 result.append("Result accurate.");
613 }
614 else {
615 result.append(message());
616 }
617 if (silent()) {
618 result.append("\n"+gammalib::parformat("Warnings")+"suppressed");
619 }
620 else {
621 result.append("\n"+gammalib::parformat("Warnings"));
622 result.append("in standard output");
623 }
624
625 } // endif: chatter was not silent
626
627 // Return result
628 return result;
629}
630
631
632/*==========================================================================
633 = =
634 = Protected methods =
635 = =
636 ==========================================================================*/
637
638/***********************************************************************//**
639 * @brief Initialise class members
640 ***************************************************************************/
642{
643 // Initialise members
644 m_kernels = NULL;
645 m_eps = 1.0e-6;
646 m_max_iter = 20;
647 m_fix_iter = 0;
648 m_message.clear();
649 m_silent = false;
650
651 // Initialise results
652 m_iter = 0;
653 m_calls = 0;
654 m_isvalid = true;
655 m_has_abserr = false;
656 m_has_relerr = false;
657 m_abserr.clear();
658 m_relerr.clear();
659
660 // Return
661 return;
662}
663
664
665/***********************************************************************//**
666 * @brief Copy class members
667 *
668 * @param[in] integral Integral.
669 ***************************************************************************/
671{
672 // Copy attributes
673 m_kernels = integral.m_kernels;
674 m_eps = integral.m_eps;
675 m_max_iter = integral.m_max_iter;
676 m_fix_iter = integral.m_fix_iter;
677 m_message = integral.m_message;
678 m_silent = integral.m_silent;
679
680 // Copy results
681 m_iter = integral.m_iter;
682 m_calls = integral.m_calls;
683 m_isvalid = integral.m_isvalid;
684 m_has_abserr = integral.m_has_abserr;
685 m_has_relerr = integral.m_has_relerr;
686 m_abserr = integral.m_abserr;
687 m_relerr = integral.m_relerr;
688
689 // Return
690 return;
691}
692
693
694/***********************************************************************//**
695 * @brief Delete class members
696 ***************************************************************************/
698{
699 // Return
700 return;
701}
702
703
704/***********************************************************************//**
705 * @brief Perform Polynomial interpolation
706 *
707 * @param[in] xa Pointer to array of X values.
708 * @param[in] ya Pointer to GVector of Y values.
709 * @param[in] order Number of elements in arrays.
710 * @param[in] x X value for which interpolations should be performed.
711 * @param[out] dy Pointer to vector of error estimates for interpolated values.
712 * @return Vector of interpolated values.
713 *
714 * Given arrays @p xa[1,..,n] and @p ya[1,..,n], and given a value @p x, this
715 * method returns a value y, and an error estimate @p dy. If P(x) is the
716 * polynomial of degree n-1, then the returned value y=P(x).
717 ***************************************************************************/
719 const GVector* ya,
720 const int& order,
721 const double& x,
722 GVector* dy)
723{
724 // Get vector dimension
725 int nsize = ya->size();
726
727 // Initialise result
728 GVector y(nsize);
729
730 // Allocate temporary memory
731 double* c = new double[order];
732 double* d = new double[order];
733
734 // Find index nclosest of the closest table entry
735 int nclosest = 0;
736 double dif = std::abs(x-xa[1]);
737 for (int i = 1; i < order; ++i) {
738 double dift = std::abs(x-xa[i+1]);
739 if (dift < dif) {
740 nclosest = i;
741 dif = dift;
742 }
743 }
744
745 // Loop over vector dimension
746 for (int index = 0; index < nsize; ++index) {
747
748 // Set closest table entry
749 int ns = nclosest;
750
751 // Initialise table values
752 for (int i = 0; i < order; ++i) {
753 double value = ya[i+1][index];
754 c[i] = value;
755 d[i] = value;
756 }
757
758 // Get initial approximation to y
759 y[index] = ya[ns+1][index];
760 ns--;
761
762 // Loop over each column of the tableau
763 for (int m = 1; m < order; ++m) {
764
765 // Update current c's and d's
766 for (int i = 0; i < order-m; ++i) {
767 double ho = xa[i+1] - x;
768 double hp = xa[i+m+1] - x;
769 double w = c[i+1] - d[i];
770 double den = ho - hp;
771 if (den == 0.0) {
772 m_isvalid = false;
773 m_message = "Invalid step size "+gammalib::str(den)+
774 " encountered. Two values in xa array are"
775 " identical.";
776 if (!m_silent) {
778 }
779 }
780 den = w/den;
781 d[i] = hp*den;
782 c[i] = ho*den;
783 }
784
785 // Compute y correction
786 double delta_y = (2*(ns+1) < (order-m)) ? c[ns+1] : d[ns--];
787
788 // Update y
789 y[index] += delta_y;
790
791 // Store result
792 (*dy)[index] = delta_y;
793
794 } // endfor: looped over columns of tableau
795
796 } // endfor: looped over vector dimension
797
798 // Free temporary memory
799 delete [] c;
800 delete [] d;
801
802 // Return
803 return y;
804}
Exception handler interface definition.
Single parameter functions abstract base class definition.
#define G_TRAPZD
Definition GIntegral.cpp:38
#define G_POLINT
Definition GIntegral.cpp:39
#define G_ROMBERG1
#define G_ROMBERG2
Integration class for set of functions interface definition.
Gammalib tools definition.
GChatter
Definition GTypemaps.hpp:33
@ SILENT
Definition GTypemaps.hpp:34
GVector abs(const GVector &vector)
Computes absolute of vector elements.
Definition GVector.cpp:1253
Single parameter functions abstract base class.
virtual GVector eval(const double &x)=0
virtual int size(void) const =0
Integration class for set of functions.
GVector polint(const double *xa, const GVector *ya, const int &order, const double &x, GVector *dy)
Perform Polynomial interpolation.
GVector romberg(std::vector< double > bounds, const int &order=5)
Perform Romberg integration.
void copy_members(const GIntegrals &integral)
Copy class members.
GVector m_relerr
Absolute integration errors.
GFunctions * m_kernels
Pointer to function kernels.
GVector m_abserr
Absolute integration errors.
const std::string & message(void) const
Return integration status message.
void free_members(void)
Delete class members.
const bool & silent(void) const
Get silence flag.
double m_eps
Requested relative integration precision.
bool m_has_relerr
Has relative integration errors.
int m_iter
Number of iterations used.
bool m_has_abserr
Has absolute integration errors.
const bool & is_valid(void) const
Signal if integration result is valid.
const int & calls(void) const
Get number of function calls.
GIntegrals(void)
Void constructor.
int m_calls
Number of function calls used.
GIntegrals * clone(void) const
Clone integral.
const double & eps(void) const
Get relative precision.
std::string print(const GChatter &chatter=NORMAL) const
Print integral information.
GIntegrals & operator=(const GIntegrals &integral)
Assignment operator.
void clear(void)
Clear integral.
GVector trapzd(const double &a, const double &b, const int &n, const GVector &previous_result)
Perform Trapezoidal integration for a set of functions.
bool m_isvalid
Integration result valid (true=yes)
const int & fixed_iter(void) const
Return fixed number of iterations.
void init_members(void)
Initialise class members.
const GFunctions * kernels(void) const
Get function kernels.
const int & max_iter(void) const
Return maximum number of iterations.
bool m_silent
Suppress integration warnings in console.
int m_fix_iter
Fixed number of iterations.
std::string m_message
Status message (if result is invalid)
int m_max_iter
Maximum number of iterations.
const int & iter(void) const
Return number of iterations.
virtual ~GIntegrals(void)
Destructor.
Vector class.
Definition GVector.hpp:46
std::string print(const GChatter &chatter=NORMAL) const
Print vector information.
Definition GVector.cpp:661
void clear(void)
Clear vector.
Definition GVector.cpp:489
const int & size(void) const
Return size of vector.
Definition GVector.hpp:178
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition GTools.cpp:1143
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition GTools.cpp:489
void warning(const std::string &origin, const std::string &message)
Emits warning.
Definition GTools.cpp:1386