File indexing completed on 2024-05-12 03:47:45

0001 /*
0002     File                 : functions.cpp
0003     Project              : LabPlot
0004     Description          : definition of functions
0005     --------------------------------------------------------------------
0006     SPDX-FileCopyrightText: 2014 Alexander Semke <alexander.semke@web.de>
0007     SPDX-FileCopyrightText: 2014-2021 Stefan Gerlach <stefan.gerlach@uni.kn>
0008     SPDX-License-Identifier: GPL-2.0-or-later
0009 */
0010 
0011 #include "functions.h"
0012 #include "backend/nsl/nsl_math.h"
0013 #include "backend/nsl/nsl_sf_basic.h"
0014 #include "parser.h"
0015 #include "parserFunctionTypes.h"
0016 
0017 #include <KLocalizedString>
0018 
0019 #include <gsl/gsl_cdf.h>
0020 #include <gsl/gsl_math.h>
0021 #include <gsl/gsl_randist.h>
0022 #include <gsl/gsl_sf.h>
0023 
0024 #ifdef _MSC_VER
0025 /* avoid intrinsics */
0026 #pragma function(ceil, floor)
0027 #endif
0028 
0029 // Function definitions
0030 double greaterThan(const double v1, const double v2);
0031 double greaterEqualThan(const double v1, const double v2);
0032 double lessThan(const double v1, const double v2);
0033 double lessEqualThan(const double v1, const double v2);
0034 double equal(const double v1, const double v2);
0035 double ifCondition(const double condition, const double valueIfTrue, const double valueIfFalse);
0036 double andFunction(const double v1, const double v2);
0037 double orFunction(const double v1, const double v2);
0038 double xorFunction(const double v1, const double v2);
0039 double notFunction(const double v);
0040 double between(const double x, const double min, const double max);
0041 double outside(const double x, const double min, const double max);
0042 double equalEpsilon(const double v1, const double v2, const double epsilon);
0043 double betweenIncluded(const double x, const double min, const double max);
0044 double outsideIncluded(const double x, const double min, const double max);
0045 double roundn(const double v, const double precision);
0046 
0047 // Parameter function definitions
0048 QString parameterXE(int parameterIndex);
0049 QString ifParameterNames(int parameterIndex);
0050 QString nsl_sf_mathieuParameterNames(int parameterIndex);
0051 QString betweenOutsideParameterNames(int parameterIndex);
0052 QString equalEpsilonParameterNames(int parameterIndex);
0053 
0054 QString FunctionGroupsToString(FunctionGroups group) {
0055     switch (group) {
0056     case FunctionGroups::StandardMathematicalFunctions:
0057         return i18n("Standard Mathematical Functions");
0058     case FunctionGroups::ComparisonFunctions:
0059         return i18n("Comparison Functions");
0060     case FunctionGroups::LogicalFunctions:
0061         return i18n("Logical Functions");
0062     case FunctionGroups::ColumnStatistics:
0063         return i18n("Column Statistics");
0064     case FunctionGroups::MovingStatistics:
0065         return i18n("Moving Statistics");
0066     case FunctionGroups::AiryFunctionsAndDerivatives:
0067         return i18n("Airy Functions and Derivatives");
0068     case FunctionGroups::BesselFunctions:
0069         return i18n("Bessel Functions");
0070     case FunctionGroups::ClausenFunctions:
0071         return i18n("Clausen Functions");
0072     case FunctionGroups::CoulombFunctions:
0073         return i18n("Coulomb Functions");
0074     case FunctionGroups::DawsonFunction:
0075         return i18n("Dawson Function");
0076     case FunctionGroups::DebyeFunctions:
0077         return i18n("Debye Functions");
0078     case FunctionGroups::Dilogarithm:
0079         return i18n("Dilogarithm");
0080     case FunctionGroups::EllipticIntegrals:
0081         return i18n("Elliptic Integrals");
0082 
0083 #ifndef _MSC_VER
0084     case FunctionGroups::ErrorFunctions:
0085         return i18n("Error Functions and Related Functions");
0086 #else
0087     case FunctionGroups::ErrorFunctions:
0088         return i18n("Error Functions");
0089 #endif
0090     case FunctionGroups::ExponentialFunctions:
0091         return i18n("Exponential Functions");
0092     case FunctionGroups::ExponentialIntegrals:
0093         return i18n("Exponential Integrals");
0094     case FunctionGroups::FermiDiracFunction:
0095         return i18n("Fermi-Dirac Function");
0096     case FunctionGroups::GammaAndBetaFunctions:
0097         return i18n("Gamma and Beta Functions");
0098     case FunctionGroups::GegenbauerFunctions:
0099         return i18n("Gegenbauer Functions");
0100 #if (GSL_MAJOR_VERSION > 2) || (GSL_MAJOR_VERSION == 2) && (GSL_MINOR_VERSION >= 4)
0101     case FunctionGroups::HermitePolynomialsAndFunctions:
0102         return i18n("Hermite Polynomials and Functions");
0103 #endif
0104     case FunctionGroups::HypergeometricFunctions:
0105         return i18n("Hypergeometric Functions");
0106     case FunctionGroups::LaguerreFunctions:
0107         return i18n("Laguerre Functions");
0108     case FunctionGroups::LambertWFunctions:
0109         return i18n("Lambert W Functions");
0110     case FunctionGroups::LegendreFunctionsAndSphericalHarmonics:
0111         return i18n("Legendre Functions and Spherical Harmonics");
0112     case FunctionGroups::LogarithmAndRelatedFunctions:
0113         return i18n("Logarithm and Related Functions");
0114 #if (GSL_MAJOR_VERSION >= 2)
0115     case FunctionGroups::MathieuFunctions:
0116         return i18n("Mathieu Functions");
0117 #endif
0118     case FunctionGroups::PowerFunction:
0119         return i18n("Power Function");
0120     case FunctionGroups::PsiDigammaFunction:
0121         return i18n("Psi (Digamma) Function");
0122     case FunctionGroups::SynchrotronFunctions:
0123         return i18n("Synchrotron Functions");
0124     case FunctionGroups::TransportFunctions:
0125         return i18n("Transport Functions");
0126     case FunctionGroups::TrigonometricFunctions:
0127         return i18n("Trigonometric Functions");
0128     case FunctionGroups::ZetaFunctions:
0129         return i18n("Zeta Functions");
0130     case FunctionGroups::RandomNumberGenerator:
0131         return i18n("Random number generator");
0132     case FunctionGroups::GaussianDistribution:
0133         return i18n("Gaussian Distribution");
0134     case FunctionGroups::ExponentialDistribution:
0135         return i18n("Exponential Distribution");
0136     case FunctionGroups::LaplaceDistribution:
0137         return i18n("Laplace Distribution");
0138     case FunctionGroups::ExponentialPowerDistribution:
0139         return i18n("Exponential Power Distribution");
0140     case FunctionGroups::CauchyDistribution:
0141         return i18n("Cauchy Distribution");
0142     case FunctionGroups::RayleighDistribution:
0143         return i18n("Rayleigh Distribution");
0144     case FunctionGroups::LandauDistribution:
0145         return i18n("Landau Distribution");
0146     case FunctionGroups::GammaDistribution:
0147         return i18n("Gamma Distribution");
0148     case FunctionGroups::FlatUniformDistribution:
0149         return i18n("Flat (Uniform) Distribution");
0150     case FunctionGroups::LognormalDistribution:
0151         return i18n("Lognormal Distribution");
0152     case FunctionGroups::ChisquaredDistribution:
0153         return i18n("Chi-squared Distribution");
0154     case FunctionGroups::Fdistribution:
0155         return i18n("F-distribution");
0156     case FunctionGroups::Tdistribution:
0157         return i18n("t-distribution");
0158     case FunctionGroups::BetaDistribution:
0159         return i18n("Beta Distribution");
0160     case FunctionGroups::LogisticDistribution:
0161         return i18n("Logistic Distribution");
0162     case FunctionGroups::ParetoDistribution:
0163         return i18n("Pareto Distribution");
0164     case FunctionGroups::WeibullDistribution:
0165         return i18n("Weibull Distribution");
0166     case FunctionGroups::GumbelDistribution:
0167         return i18n("Gumbel Distribution");
0168     case FunctionGroups::PoissonDistribution:
0169         return i18n("Poisson Distribution");
0170     case FunctionGroups::BernoulliDistribution:
0171         return i18n("Bernoulli Distribution");
0172     case FunctionGroups::BinomialDistribution:
0173         return i18n("Binomial Distribution");
0174     case FunctionGroups::PascalDistribution:
0175         return i18n("Pascal Distribution");
0176     case FunctionGroups::GeometricDistribution:
0177         return i18n("Geometric Distribution");
0178     case FunctionGroups::HypergeometricDistribution:
0179         return i18n("Hypergeometric Distribution");
0180     case FunctionGroups::LogarithmicDistribution:
0181         return i18n("Logarithmic Distribution");
0182     case FunctionGroups::END:
0183         break;
0184     }
0185     return i18n("Unknown Function");
0186 }
0187 
0188 const char* colfun_size = "size";
0189 const char* colfun_min = "min";
0190 const char* colfun_max = "max";
0191 const char* colfun_mean = "mean";
0192 const char* colfun_median = "median";
0193 const char* colfun_stdev = "stdev";
0194 const char* colfun_var = "var";
0195 const char* colfun_gm = "gm";
0196 const char* colfun_hm = "hm";
0197 const char* colfun_chm = "chm";
0198 const char* colfun_mode = "mode";
0199 const char* colfun_quartile1 = "quartile1";
0200 const char* colfun_quartile3 = "quartile3";
0201 const char* colfun_iqr = "iqr";
0202 const char* colfun_percentile1 = "percentile1";
0203 const char* colfun_percentile5 = "percentile5";
0204 const char* colfun_percentile10 = "percentile10";
0205 const char* colfun_percentile90 = "percentile90";
0206 const char* colfun_percentile95 = "percentile95";
0207 const char* colfun_percentile99 = "percentile99";
0208 const char* colfun_trimean = "trimean";
0209 const char* colfun_meandev = "meandev";
0210 const char* colfun_meandevmedian = "meandevmedian";
0211 const char* colfun_mediandev = "mediandev";
0212 const char* colfun_skew = "skew";
0213 const char* colfun_kurt = "kurt";
0214 const char* colfun_entropy = "entropy";
0215 const char* colfun_quantile = "quantile";
0216 const char* colfun_percentile = "percentile";
0217 
0218 const char* specialfun_cell = "cell";
0219 const char* specialfun_ma = "ma";
0220 const char* specialfun_mr = "mr";
0221 const char* specialfun_smmin = "smmin";
0222 const char* specialfun_smmax = "smmax";
0223 const char* specialfun_sma = "sma";
0224 const char* specialfun_smr = "smr";
0225 
0226 // clang-format off
0227 
0228 // Special functions depending on variables
0229 struct funs _special_functions[] = {
0230     // Moving Statistics
0231     // Important: when adding new function, implement them in Expressionhandler or somewhere else!
0232     {[]() { return i18n("Cell (index, variable)"); }, specialfun_cell, func_t2Payload(), 2, nullptr, FunctionGroups::MovingStatistics},
0233     {[]() { return i18n("Moving Average"); }, specialfun_ma, func_t1Payload(), 1, nullptr, FunctionGroups::MovingStatistics},
0234     {[]() { return i18n("Moving Range"); }, specialfun_mr, func_t1Payload(), 1, nullptr, FunctionGroups::MovingStatistics},
0235     {[]() { return i18n("Simple Moving Minimum"); }, specialfun_smmin, func_t2Payload(), 2, nullptr, FunctionGroups::MovingStatistics},
0236     {[]() { return i18n("Simple Moving Maximum"); }, specialfun_smmax, func_t2Payload(), 2, nullptr, FunctionGroups::MovingStatistics},
0237     {[]() { return i18n("Simple Moving Average"); }, specialfun_sma, func_t2Payload(), 2, nullptr, FunctionGroups::MovingStatistics},
0238     {[]() { return i18n("Simple Moving Range"); }, specialfun_smr, func_t2Payload(), 2, nullptr, FunctionGroups::MovingStatistics},
0239 
0240     // Values independend of the row index!!!
0241     // Important: When adding function here, implement it somewhere. For example column functions are implemented in ColumnPrivate!
0242     {[]() { return i18n("Size"); }, colfun_size, func_t1Payload(), 1, nullptr, FunctionGroups::ColumnStatistics},
0243     {[]() { return i18n("Minimum"); }, colfun_min, func_t1Payload(), 1, nullptr, FunctionGroups::ColumnStatistics},
0244     {[]() { return i18n("Maximum"); }, colfun_max, func_t1Payload(), 1, nullptr, FunctionGroups::ColumnStatistics},
0245     {[]() { return i18n("Arithmetic mean"); }, colfun_mean, func_t1Payload(), 1, nullptr, FunctionGroups::ColumnStatistics},
0246     {[]() { return i18n("Median"); }, colfun_median, func_t1Payload(), 1, nullptr, FunctionGroups::ColumnStatistics},
0247     {[]() { return i18n("Standard deviation"); }, colfun_stdev, func_t1Payload(), 1, nullptr, FunctionGroups::ColumnStatistics},
0248     {[]() { return i18n("Variance"); }, colfun_var, func_t1Payload(), 1, nullptr, FunctionGroups::ColumnStatistics},
0249     {[]() { return i18n("Geometric mean"); }, colfun_gm, func_t1Payload(), 1, nullptr, FunctionGroups::ColumnStatistics},
0250     {[]() { return i18n("Harmonic mean"); }, colfun_hm, func_t1Payload(), 1, nullptr, FunctionGroups::ColumnStatistics},
0251     {[]() { return i18n("Contraharmonic mean"); }, colfun_chm, func_t1Payload(), 1, nullptr, FunctionGroups::ColumnStatistics},
0252     {[]() { return i18n("Mode"); }, colfun_mode, func_t1Payload(), 1, nullptr, FunctionGroups::ColumnStatistics},
0253     {[]() { return i18n("First quartile"); }, colfun_quartile1, func_t1Payload(), 1, nullptr, FunctionGroups::ColumnStatistics},
0254     {[]() { return i18n("Third quartile"); }, colfun_quartile3, func_t1Payload(), 1, nullptr, FunctionGroups::ColumnStatistics},
0255     {[]() { return i18n("Interquartile range"); }, colfun_iqr, func_t1Payload(), 1, nullptr, FunctionGroups::ColumnStatistics},
0256     {[]() { return i18n("1st percentile"); }, colfun_percentile1, func_t1Payload(), 1, nullptr, FunctionGroups::ColumnStatistics},
0257     {[]() { return i18n("5th percentile"); }, colfun_percentile5, func_t1Payload(), 1, nullptr, FunctionGroups::ColumnStatistics},
0258     {[]() { return i18n("10th percentile"); }, colfun_percentile10, func_t1Payload(), 1, nullptr, FunctionGroups::ColumnStatistics},
0259     {[]() { return i18n("90th percentile"); }, colfun_percentile90, func_t1Payload(), 1, nullptr, FunctionGroups::ColumnStatistics},
0260     {[]() { return i18n("95th percentile"); }, colfun_percentile95, func_t1Payload(), 1, nullptr, FunctionGroups::ColumnStatistics},
0261     {[]() { return i18n("99th percentile"); }, colfun_percentile99, func_t1Payload(), 1, nullptr, FunctionGroups::ColumnStatistics},
0262     {[]() { return i18n("Trimean"); }, colfun_trimean, func_t1Payload(), 1, nullptr, FunctionGroups::ColumnStatistics},
0263     {[]() { return i18n("Mean absolute deviation"); }, colfun_meandev, func_t1Payload(), 1, nullptr, FunctionGroups::ColumnStatistics},
0264     {[]() { return i18n("Mean absolute deviation around median"); }, colfun_meandevmedian, func_t1Payload(), 1, nullptr, FunctionGroups::ColumnStatistics},
0265     {[]() { return i18n("Median absolute deviation"); }, colfun_mediandev, func_t1Payload(), 1, nullptr, FunctionGroups::ColumnStatistics},
0266     {[]() { return i18n("Skewness"); }, colfun_skew, func_t1Payload(), 1, nullptr, FunctionGroups::ColumnStatistics},
0267     {[]() { return i18n("Kurtosis"); }, colfun_kurt, func_t1Payload(), 1, nullptr, FunctionGroups::ColumnStatistics},
0268     {[]() { return i18n("Entropy"); }, colfun_entropy, func_t1Payload(), 1, nullptr, FunctionGroups::ColumnStatistics},
0269     {[]() { return i18n("Quantile"); }, colfun_quantile, func_t2Payload(), 2, nullptr, FunctionGroups::ColumnStatistics},
0270     {[]() { return i18n("Percentile"); }, colfun_percentile, func_t2Payload(), 2, nullptr, FunctionGroups::ColumnStatistics},
0271 };
0272 const int _number_specialfunctions = sizeof(_special_functions) / sizeof(funs);
0273 
0274 /* list of functions (sync with ExpressionParser.cpp!) */
0275 struct funs _functions[] = {
0276     // Standard Mathematical Functions
0277     {[]() { return i18n("pseudo-random integer [0, RAND_MAX]"); }, "rand", nsl_sf_rand, 0, nullptr, FunctionGroups::StandardMathematicalFunctions},
0278     {[]() { return i18n("nonlinear additive feedback rng [0, RAND_MAX]"); }, "random", nsl_sf_random, 0, nullptr, FunctionGroups::StandardMathematicalFunctions},
0279     {[]() { return i18n("nonlinear additive feedback rng [0, 1]"); }, "drand", nsl_sf_drand, 0, nullptr, FunctionGroups::StandardMathematicalFunctions},
0280     {[]() { return i18n("Smallest integral value not less"); }, "ceil", static_cast<double (*)(double)>(&ceil), 1, nullptr, FunctionGroups::StandardMathematicalFunctions},
0281     {[]() { return i18n("Absolute value"); }, "fabs", static_cast<double (*)(double)>(&fabs), 1, nullptr, FunctionGroups::StandardMathematicalFunctions},
0282 
0283     {[]() { return i18n("Base 10 logarithm"); }, "log10", static_cast<double (*)(double)>(&log10), 1, nullptr, FunctionGroups::StandardMathematicalFunctions},
0284     {[]() { return i18n("Power function [x^y]"); }, "pow", static_cast<double (*)(double, double)>(&pow), 2, nullptr, FunctionGroups::StandardMathematicalFunctions},
0285     {[]() { return i18n("Nonnegative square root"); }, "sqrt", static_cast<double (*)(double)>(&sqrt), 1, nullptr, FunctionGroups::StandardMathematicalFunctions},
0286     {[]() { return i18n("Sign function"); }, "sgn", nsl_sf_sgn, 1, nullptr, FunctionGroups::StandardMathematicalFunctions},
0287     {[]() { return i18n("Heavyside theta function"); }, "theta", nsl_sf_theta, 1, nullptr, FunctionGroups::StandardMathematicalFunctions},
0288     {[]() { return i18n("Harmonic number function"); }, "harmonic", nsl_sf_harmonic, 1, nullptr, FunctionGroups::StandardMathematicalFunctions},
0289 
0290     {[]() { return i18n("Cube root"); }, "cbrt", static_cast<double (*)(double)>(&cbrt), 1, nullptr, FunctionGroups::StandardMathematicalFunctions},
0291     {[]() { return i18n("Extract the exponent"); }, "logb", static_cast<double (*)(double)>(&logb), 1, nullptr, FunctionGroups::StandardMathematicalFunctions},
0292     {[]() { return i18n("Round to an integer value"); }, "rint", static_cast<double (*)(double)>(&rint), 1, nullptr, FunctionGroups::StandardMathematicalFunctions},
0293     {[]() { return i18n("Round to the nearest integer"); }, "round", static_cast<double (*)(double)>(&round), 1, nullptr, FunctionGroups::StandardMathematicalFunctions},
0294     {[]() { return i18n("Round to the nearest integer"); }, "trunc", static_cast<double (*)(double)>(&trunc), 1, nullptr, FunctionGroups::StandardMathematicalFunctions},
0295     {[]() { return i18n("Round to y decimal places"); }, "roundn", static_cast<double (*)(double, double)>(&roundn), 2, nullptr, FunctionGroups::StandardMathematicalFunctions},
0296     {[]() { return QStringLiteral("log(1+x)"); }, "log1p", gsl_log1p, 1, nullptr, FunctionGroups::StandardMathematicalFunctions},
0297     {[]() { return QStringLiteral("x * 2^e"); }, "ldexp", nsl_sf_ldexp, 2, &parameterXE, FunctionGroups::StandardMathematicalFunctions},
0298     {[]() { return QStringLiteral("x^y"); }, "powint", nsl_sf_powint, 2, nullptr, FunctionGroups::StandardMathematicalFunctions},
0299     {[]() { return QStringLiteral("x^2"); }, "pow2", gsl_pow_2, 1, nullptr, FunctionGroups::StandardMathematicalFunctions},
0300     {[]() { return QStringLiteral("x^3"); }, "pow3", gsl_pow_3, 1, nullptr, FunctionGroups::StandardMathematicalFunctions},
0301     {[]() { return QStringLiteral("x^4"); }, "pow4", gsl_pow_4, 1, nullptr, FunctionGroups::StandardMathematicalFunctions},
0302     {[]() { return QStringLiteral("x^5"); }, "pow5", gsl_pow_5, 1, nullptr, FunctionGroups::StandardMathematicalFunctions},
0303     {[]() { return QStringLiteral("x^6"); }, "pow6", gsl_pow_6, 1, nullptr, FunctionGroups::StandardMathematicalFunctions},
0304     {[]() { return QStringLiteral("x^7"); }, "pow7", gsl_pow_7, 1, nullptr, FunctionGroups::StandardMathematicalFunctions},
0305     {[]() { return QStringLiteral("x^8"); }, "pow8", gsl_pow_8, 1, nullptr, FunctionGroups::StandardMathematicalFunctions},
0306     {[]() { return QStringLiteral("x^9"); }, "pow9", gsl_pow_9, 1, nullptr, FunctionGroups::StandardMathematicalFunctions},
0307 
0308     // Comparison Functions
0309     {[]() { return i18n("greaterThan"); }, "greaterThan", greaterThan, 2, nullptr, FunctionGroups::ComparisonFunctions},
0310     {[]() { return i18n("lessThan"); }, "lessThan", lessThan, 2, nullptr, FunctionGroups::ComparisonFunctions},
0311     {[]() { return i18n("greaterEqualThan"); }, "greaterEqualThan", greaterEqualThan, 2, nullptr, FunctionGroups::ComparisonFunctions},
0312     {[]() { return i18n("lessEqualThan"); }, "lessEqualThan", lessEqualThan, 2, nullptr, FunctionGroups::ComparisonFunctions},
0313     {[]() { return i18n("equal"); }, "equal", equal, 2, nullptr, FunctionGroups::ComparisonFunctions},
0314     {[]() { return i18n("equal with epsilon"); }, "equalE", equalEpsilon, 3, &equalEpsilonParameterNames, FunctionGroups::ComparisonFunctions},
0315     {[]() { return i18n("between with boundaries included"); }, "between_inc", betweenIncluded, 3, &betweenOutsideParameterNames, FunctionGroups::ComparisonFunctions},
0316     {[]() { return i18n("outside with boundaries included"); }, "outside_inc", outsideIncluded, 3, &betweenOutsideParameterNames, FunctionGroups::ComparisonFunctions},
0317     {[]() { return i18n("between with boundaries excluded"); }, "between", between, 3, &betweenOutsideParameterNames, FunctionGroups::ComparisonFunctions},
0318     {[]() { return i18n("outside with boundaries excluded"); }, "outside", outside, 3, &betweenOutsideParameterNames, FunctionGroups::ComparisonFunctions},
0319 
0320     // Logical
0321     {[]() { return i18n("if(condition; ifTrue; ifFalse)"); }, "if", ifCondition, 3, &ifParameterNames, FunctionGroups::LogicalFunctions},
0322     {[]() { return i18n("and"); }, "and", andFunction, 2, nullptr, FunctionGroups::LogicalFunctions},
0323     {[]() { return i18n("or"); }, "or", orFunction, 2, nullptr, FunctionGroups::LogicalFunctions},
0324     {[]() { return i18n("xor"); }, "xor", xorFunction, 2, nullptr, FunctionGroups::LogicalFunctions},
0325     {[]() { return i18n("not"); }, "not", notFunction, 1, nullptr, FunctionGroups::LogicalFunctions},
0326 
0327     // https://www.gnu.org/software/gsl/doc/html/specfunc.html
0328     // Airy Functions and Derivatives
0329     {[]() { return i18n("Airy function of the first kind"); }, "Ai", nsl_sf_airy_Ai, 1, nullptr, FunctionGroups::AiryFunctionsAndDerivatives},
0330     {[]() { return i18n("Airy function of the second kind"); }, "Bi", nsl_sf_airy_Bi, 1, nullptr, FunctionGroups::AiryFunctionsAndDerivatives},
0331     {[]() { return i18n("Scaled Airy function of the first kind"); }, "Ais", nsl_sf_airy_Ais, 1, nullptr, FunctionGroups::AiryFunctionsAndDerivatives},
0332     {[]() { return i18n("Scaled Airy function of the second kind"); }, "Bis", nsl_sf_airy_Bis, 1, nullptr, FunctionGroups::AiryFunctionsAndDerivatives},
0333     {[]() { return i18n("Airy function derivative of the first kind"); }, "Aid", nsl_sf_airy_Aid, 1, nullptr, FunctionGroups::AiryFunctionsAndDerivatives},
0334     {[]() { return i18n("Airy function derivative of the second kind"); }, "Bid", nsl_sf_airy_Bid, 1, nullptr, FunctionGroups::AiryFunctionsAndDerivatives},
0335     {[]() { return i18n("Scaled Airy function derivative of the first kind"); }, "Aids", nsl_sf_airy_Aids, 1, nullptr, FunctionGroups::AiryFunctionsAndDerivatives},
0336     {[]() { return i18n("Scaled Airy function derivative of the second kind"); }, "Bids", nsl_sf_airy_Bids, 1, nullptr, FunctionGroups::AiryFunctionsAndDerivatives},
0337     {[]() { return i18n("n-th zero of the Airy function of the first kind"); }, "Ai0", nsl_sf_airy_0_Ai, 1, nullptr, FunctionGroups::AiryFunctionsAndDerivatives},
0338     {[]() { return i18n("n-th zero of the Airy function of the second kind"); }, "Bi0", nsl_sf_airy_0_Bi, 1, nullptr, FunctionGroups::AiryFunctionsAndDerivatives},
0339     {[]() { return i18n("n-th zero of the Airy function derivative of the first kind"); }, "Aid0", nsl_sf_airy_0_Aid, 1, nullptr, FunctionGroups::AiryFunctionsAndDerivatives},
0340     {[]() { return i18n("n-th zero of the Airy function derivative of the second kind"); }, "Bid0", nsl_sf_airy_0_Bid, 1, nullptr, FunctionGroups::AiryFunctionsAndDerivatives},
0341 
0342     // Bessel Functions
0343     {[]() { return i18n("Regular cylindrical Bessel function of zeroth order"); }, "J0", gsl_sf_bessel_J0, 1, nullptr, FunctionGroups::BesselFunctions},
0344     {[]() { return i18n("Regular cylindrical Bessel function of first order"); }, "J1", gsl_sf_bessel_J1, 1, nullptr, FunctionGroups::BesselFunctions},
0345     {[]() { return i18n("Regular cylindrical Bessel function of order n"); }, "Jn", nsl_sf_bessel_Jn, 2, nullptr, FunctionGroups::BesselFunctions},
0346     {[]() { return i18n("Irregular cylindrical Bessel function of zeroth order"); }, "Y0", gsl_sf_bessel_Y0, 1, nullptr, FunctionGroups::BesselFunctions},
0347     {[]() { return i18n("Irregular cylindrical Bessel function of first order"); }, "Y1", gsl_sf_bessel_Y1, 1, nullptr, FunctionGroups::BesselFunctions},
0348     {[]() { return i18n("Irregular cylindrical Bessel function of order n"); }, "Yn", nsl_sf_bessel_Yn, 2, nullptr, FunctionGroups::BesselFunctions},
0349     {[]() { return i18n("Regular modified cylindrical Bessel function of zeroth order"); }, "I0", gsl_sf_bessel_I0, 1, nullptr, FunctionGroups::BesselFunctions},
0350     {[]() { return i18n("Regular modified cylindrical Bessel function of first order"); }, "I1", gsl_sf_bessel_I1, 1, nullptr, FunctionGroups::BesselFunctions},
0351     {[]() { return i18n("Regular modified cylindrical Bessel function of order n"); }, "In", nsl_sf_bessel_In, 2, nullptr, FunctionGroups::BesselFunctions},
0352     {[]() { return i18n("Scaled regular modified cylindrical Bessel function of zeroth order exp(-|x|) I0(x)"); }, "I0s", gsl_sf_bessel_I0_scaled, 1, nullptr, FunctionGroups::BesselFunctions},
0353 
0354     {[]() { return i18n("Scaled regular modified cylindrical Bessel function of first order exp(-|x|) I1(x)"); }, "I1s", gsl_sf_bessel_I1_scaled, 1, nullptr, FunctionGroups::BesselFunctions},
0355     {[]() { return i18n("Scaled regular modified cylindrical Bessel function of order n exp(-|x|) In(x)"); }, "Ins", nsl_sf_bessel_Ins, 2, nullptr, FunctionGroups::BesselFunctions},
0356     {[]() { return i18n("Irregular modified cylindrical Bessel function of zeroth order"); }, "K0", gsl_sf_bessel_K0, 1, nullptr, FunctionGroups::BesselFunctions},
0357     {[]() { return i18n("Irregular modified cylindrical Bessel function of first order"); }, "K1", gsl_sf_bessel_K1, 1, nullptr, FunctionGroups::BesselFunctions},
0358     {[]() { return i18n("Irregular modified cylindrical Bessel function of order n"); }, "Kn", nsl_sf_bessel_Kn, 2, nullptr, FunctionGroups::BesselFunctions},
0359     {[]() { return i18n("Scaled irregular modified cylindrical Bessel function of zeroth order exp(x) K0(x)"); }, "K0s", gsl_sf_bessel_K0_scaled, 1, nullptr, FunctionGroups::BesselFunctions},
0360     {[]() { return i18n("Scaled irregular modified cylindrical Bessel function of first order exp(x) K1(x)"); }, "K1s", gsl_sf_bessel_K1_scaled, 1, nullptr, FunctionGroups::BesselFunctions},
0361     {[]() { return i18n("Scaled irregular modified cylindrical Bessel function of order n exp(x) Kn(x)"); }, "Kns", nsl_sf_bessel_Kns, 2, nullptr, FunctionGroups::BesselFunctions},
0362     {[]() { return i18n("Regular spherical Bessel function of zeroth order"); }, "j0", gsl_sf_bessel_j0, 1, nullptr, FunctionGroups::BesselFunctions},
0363     {[]() { return i18n("Regular spherical Bessel function of first order"); }, "j1", gsl_sf_bessel_j1, 1, nullptr, FunctionGroups::BesselFunctions},
0364 
0365     {[]() { return i18n("Regular spherical Bessel function of second order"); }, "j2", gsl_sf_bessel_j2, 1, nullptr, FunctionGroups::BesselFunctions},
0366     {[]() { return i18n("Regular spherical Bessel function of order l"); }, "jl", nsl_sf_bessel_jl, 2, nullptr, FunctionGroups::BesselFunctions},
0367     {[]() { return i18n("Irregular spherical Bessel function of zeroth order"); }, "y0", gsl_sf_bessel_y0, 1, nullptr, FunctionGroups::BesselFunctions},
0368     {[]() { return i18n("Irregular spherical Bessel function of first order"); }, "y1", gsl_sf_bessel_y1, 1, nullptr, FunctionGroups::BesselFunctions},
0369     {[]() { return i18n("Irregular spherical Bessel function of second order"); }, "y2", gsl_sf_bessel_y2, 1, nullptr, FunctionGroups::BesselFunctions},
0370     {[]() { return i18n("Irregular spherical Bessel function of order l"); }, "yl", nsl_sf_bessel_yl, 2, nullptr, FunctionGroups::BesselFunctions},
0371     {[]() { return i18n("Scaled regular modified spherical Bessel function of zeroth order, exp(-|x|) i0(x)"); }, "i0s", gsl_sf_bessel_i0_scaled, 1, nullptr, FunctionGroups::BesselFunctions},
0372     {[]() { return i18n("Scaled regular modified spherical Bessel function of first order, exp(-|x|) i1(x)"); }, "i1s", gsl_sf_bessel_i1_scaled, 1, nullptr, FunctionGroups::BesselFunctions},
0373     {[]() { return i18n("Scaled regular modified spherical Bessel function of second order, exp(-|x|) i2(x)"); }, "i2s", gsl_sf_bessel_i2_scaled, 1, nullptr, FunctionGroups::BesselFunctions},
0374     {[]() { return i18n("Scaled regular modified spherical Bessel function of order l, exp(-|x|) il(x)"); }, "ils", nsl_sf_bessel_ils, 2, nullptr, FunctionGroups::BesselFunctions},
0375 
0376     {[]() { return i18n("Scaled irregular modified spherical Bessel function of zeroth order, exp(x) k0(x)"); }, "k0s", gsl_sf_bessel_k0_scaled, 1, nullptr, FunctionGroups::BesselFunctions},
0377     {[]() { return i18n("Scaled irregular modified spherical Bessel function of first order, exp(-|x|) k1(x)"); }, "k1s", gsl_sf_bessel_k1_scaled, 1, nullptr, FunctionGroups::BesselFunctions},
0378     {[]() { return i18n("Scaled irregular modified spherical Bessel function of second order, exp(-|x|) k2(x)"); }, "k2s", gsl_sf_bessel_k2_scaled, 1, nullptr, FunctionGroups::BesselFunctions},
0379     {[]() { return i18n("Scaled irregular modified spherical Bessel function of order l, exp(-|x|) kl(x)"); }, "kls", nsl_sf_bessel_kls, 2, nullptr, FunctionGroups::BesselFunctions},
0380     {[]() { return i18n("Regular cylindrical Bessel function of fractional order"); }, "Jnu", gsl_sf_bessel_Jnu, 2, nullptr, FunctionGroups::BesselFunctions},
0381     {[]() { return i18n("Irregular cylindrical Bessel function of fractional order"); }, "Ynu", gsl_sf_bessel_Ynu, 2, nullptr, FunctionGroups::BesselFunctions},
0382     {[]() { return i18n("Regular modified Bessel function of fractional order"); }, "Inu", gsl_sf_bessel_Inu, 2, nullptr, FunctionGroups::BesselFunctions},
0383     {[]() { return i18n("Scaled regular modified Bessel function of fractional order"); }, "Inus", gsl_sf_bessel_Inu_scaled, 2, nullptr, FunctionGroups::BesselFunctions},
0384     {[]() { return i18n("Irregular modified Bessel function of fractional order"); }, "Knu", gsl_sf_bessel_Knu, 2, nullptr, FunctionGroups::BesselFunctions},
0385     {[]() { return i18n("Logarithm of irregular modified Bessel function of fractional order"); }, "lnKnu", gsl_sf_bessel_lnKnu, 2, nullptr, FunctionGroups::BesselFunctions},
0386 
0387     {[]() { return i18n("Scaled irregular modified Bessel function of fractional order"); }, "Knus", gsl_sf_bessel_Knu_scaled, 2, nullptr, FunctionGroups::BesselFunctions},
0388     {[]() { return i18n("n-th positive zero of the Bessel function J0"); }, "J0_0", nsl_sf_bessel_0_J0, 1, nullptr, FunctionGroups::BesselFunctions},
0389     {[]() { return i18n("n-th positive zero of the Bessel function J1"); }, "J1_0", nsl_sf_bessel_0_J1, 1, nullptr, FunctionGroups::BesselFunctions},
0390     {[]() { return i18n("n-th positive zero of the Bessel function Jnu"); }, "Jnu_0", nsl_sf_bessel_0_Jnu, 2, nullptr, FunctionGroups::BesselFunctions},
0391 
0392     // Clausen Functions
0393     {[]() { return i18n("Clausen function"); }, "clausen", gsl_sf_clausen, 1, nullptr, FunctionGroups::ClausenFunctions},
0394 
0395     // Coulomb Functions
0396     {[]() { return i18n("Lowest-order normalized hydrogenic bound state radial wavefunction"); }, "hydrogenicR_1", gsl_sf_hydrogenicR_1, 2, nullptr, FunctionGroups::CoulombFunctions},
0397     {[]() { return i18n("n-th normalized hydrogenic bound state radial wavefunction"); }, "hydrogenicR", nsl_sf_hydrogenicR, 4, nullptr, FunctionGroups::CoulombFunctions},
0398 
0399     // Dawson Function
0400     {[]() { return i18n("Dawson's integral D(z) = sqrt(pi)/2 * exp(-z^2) * erfi(z)"); }, "dawson", nsl_sf_dawson, 1, nullptr, FunctionGroups::DawsonFunction},
0401 
0402     // Debye Functions
0403     {[]() { return i18n("First-order Debye function"); }, "D1", gsl_sf_debye_1, 1, nullptr, FunctionGroups::DebyeFunctions},
0404     {[]() { return i18n("Second-order Debye function"); }, "D2", gsl_sf_debye_2, 1, nullptr, FunctionGroups::DebyeFunctions},
0405     {[]() { return i18n("Third-order Debye function"); }, "D3", gsl_sf_debye_3, 1, nullptr, FunctionGroups::DebyeFunctions},
0406     {[]() { return i18n("Fourth-order Debye function"); }, "D4", gsl_sf_debye_4, 1, nullptr, FunctionGroups::DebyeFunctions},
0407     {[]() { return i18n("Fifth-order Debye function"); }, "D5", gsl_sf_debye_5, 1, nullptr, FunctionGroups::DebyeFunctions},
0408     {[]() { return i18n("Sixth-order Debye function"); }, "D6", gsl_sf_debye_6, 1, nullptr, FunctionGroups::DebyeFunctions},
0409 
0410     // Dilogarithm
0411     {[]() { return i18n("Dilogarithm for a real argument"); }, "Li2", gsl_sf_dilog, 1, nullptr, FunctionGroups::Dilogarithm},
0412 
0413     // Elliptic Integrals
0414     {[]() { return i18n("Legendre form of complete elliptic integral K"); }, "Kc", nsl_sf_ellint_Kc, 1, nullptr, FunctionGroups::EllipticIntegrals},
0415     {[]() { return i18n("Legendre form of complete elliptic integral E"); }, "Ec", nsl_sf_ellint_Ec, 1, nullptr, FunctionGroups::EllipticIntegrals},
0416     {[]() { return i18n("Legendre form of complete elliptic integral Pi"); }, "Pc", nsl_sf_ellint_Pc, 2, nullptr, FunctionGroups::EllipticIntegrals},
0417     {[]() { return i18n("Legendre form of incomplete elliptic integral F"); }, "F", nsl_sf_ellint_F, 2, nullptr, FunctionGroups::EllipticIntegrals},
0418     {[]() { return i18n("Legendre form of incomplete elliptic integral E"); }, "E", nsl_sf_ellint_E, 2, nullptr, FunctionGroups::EllipticIntegrals},
0419     {[]() { return i18n("Legendre form of incomplete elliptic integral P"); }, "P", nsl_sf_ellint_P, 3, nullptr, FunctionGroups::EllipticIntegrals},
0420     {[]() { return i18n("Legendre form of incomplete elliptic integral D"); }, "D", nsl_sf_ellint_D, 2, nullptr, FunctionGroups::EllipticIntegrals},
0421     {[]() { return i18n("Carlson form of incomplete elliptic integral RC"); }, "RC", nsl_sf_ellint_RC, 2, nullptr, FunctionGroups::EllipticIntegrals},
0422     {[]() { return i18n("Carlson form of incomplete elliptic integral RD"); }, "RD", nsl_sf_ellint_RD, 3, nullptr, FunctionGroups::EllipticIntegrals},
0423     {[]() { return i18n("Carlson form of incomplete elliptic integral RF"); }, "RF", nsl_sf_ellint_RF, 3, nullptr, FunctionGroups::EllipticIntegrals},
0424     {[]() { return i18n("Carlson form of incomplete elliptic integral RJ"); }, "RJ", nsl_sf_ellint_RJ, 4, nullptr, FunctionGroups::EllipticIntegrals},
0425 
0426     // Error Functions
0427     {[]() { return i18n("Error function"); }, "erf", gsl_sf_erf, 1, nullptr, FunctionGroups::ErrorFunctions},
0428     {[]() { return i18n("Complementary error function"); }, "erfc", gsl_sf_erfc, 1, nullptr, FunctionGroups::ErrorFunctions},
0429     {[]() { return i18n("Logarithm of complementary error function"); }, "log_erfc", gsl_sf_log_erfc, 1, nullptr, FunctionGroups::ErrorFunctions},
0430     {[]() { return i18n("Gaussian probability density function Z"); }, "erf_Z", gsl_sf_erf_Z, 1, nullptr, FunctionGroups::ErrorFunctions},
0431     {[]() { return i18n("Upper tail of the Gaussian probability function Q"); }, "erf_Q", gsl_sf_erf_Q, 1, nullptr, FunctionGroups::ErrorFunctions},
0432     {[]() { return i18n("Hazard function for the normal distribution Z/Q"); }, "hazard", gsl_sf_hazard, 1, nullptr, FunctionGroups::ErrorFunctions},
0433 #ifndef _MSC_VER
0434     {[]() { return i18n("Underflow-compensating function exp(x^2) erfc(x) for real x"); }, "erfcx", nsl_sf_erfcx, 1, nullptr, FunctionGroups::ErrorFunctions},
0435     {[]() { return i18n("Imaginary error function erfi(x) = -i erf(ix) for real x"); }, "erfi", nsl_sf_erfi, 1, nullptr, FunctionGroups::ErrorFunctions},
0436     {[]() { return i18n("Imaginary part of Faddeeva's scaled complex error function w(x) = exp(-x^2) erfc(-ix) for real x"); }, "im_w_of_x", nsl_sf_im_w_of_x, 1, nullptr, FunctionGroups::ErrorFunctions},
0437     {[]() { return i18n("Dawson's integral D(z) = sqrt(pi)/2 * exp(-z^2) * erfi(z)"); }, "dawson", nsl_sf_dawson, 1, nullptr, FunctionGroups::ErrorFunctions},
0438     {[]() { return i18n("Voigt profile"); }, "voigt", nsl_sf_voigt, 3, nullptr, FunctionGroups::ErrorFunctions},
0439 #endif
0440     {[]() { return i18n("Pseudo-Voigt profile (same width)"); }, "pseudovoigt1", nsl_sf_pseudovoigt1, 3, nullptr, FunctionGroups::ErrorFunctions},
0441 
0442     // Exponential Functions
0443     {[]() { return i18n("Exponential function"); }, "exp", gsl_sf_exp, 1, nullptr, FunctionGroups::ExponentialFunctions},
0444     {[]() { return i18n("exponentiate x and multiply by y"); }, "exp_mult", gsl_sf_exp_mult, 2, nullptr, FunctionGroups::ExponentialFunctions},
0445     {[]() { return QStringLiteral("exp(x) - 1"); }, "expm1", gsl_expm1, 1, nullptr, FunctionGroups::ExponentialFunctions},
0446     {[]() { return QStringLiteral("(exp(x)-1)/x"); }, "exprel", gsl_sf_exprel, 1, nullptr, FunctionGroups::ExponentialFunctions},
0447     {[]() { return QStringLiteral("2(exp(x)-1-x)/x^2"); }, "exprel2", gsl_sf_exprel_2, 1, nullptr, FunctionGroups::ExponentialFunctions},
0448     {[]() { return i18n("n-relative exponential"); }, "expreln", nsl_sf_exprel_n, 2, nullptr, FunctionGroups::ExponentialFunctions},
0449 
0450     // Exponential Integrals
0451     {[]() { return i18n("Exponential integral"); }, "E1", gsl_sf_expint_E1, 1, nullptr, FunctionGroups::ExponentialIntegrals},
0452     {[]() { return i18n("Second order exponential integral"); }, "E2", gsl_sf_expint_E2, 1, nullptr, FunctionGroups::ExponentialIntegrals},
0453     {[]() { return i18n("Exponential integral of order n"); }, "En", [](double v1, double v2) { return gsl_sf_expint_En(v1, v2); },  2, nullptr, FunctionGroups::ExponentialIntegrals},
0454     {[]() { return i18n("Exponential integral Ei"); }, "Ei", gsl_sf_expint_Ei, 1, nullptr, FunctionGroups::ExponentialIntegrals},
0455     {[]() { return i18n("Hyperbolic integral Shi"); }, "Shi", gsl_sf_Shi, 1, nullptr, FunctionGroups::ExponentialIntegrals},
0456     {[]() { return i18n("Hyperbolic integral Chi"); }, "Chi", gsl_sf_Chi, 1, nullptr, FunctionGroups::ExponentialIntegrals},
0457     {[]() { return i18n("Third-order exponential integral"); }, "Ei3", gsl_sf_expint_3, 1, nullptr, FunctionGroups::ExponentialIntegrals},
0458     {[]() { return i18n("Sine integral"); }, "Si", gsl_sf_Si, 1, nullptr, FunctionGroups::ExponentialIntegrals},
0459     {[]() { return i18n("Cosine integral"); }, "Ci", gsl_sf_Ci, 1, nullptr, FunctionGroups::ExponentialIntegrals},
0460     {[]() { return i18n("Arctangent integral"); }, "Atanint", gsl_sf_atanint, 1, nullptr, FunctionGroups::ExponentialIntegrals},
0461 
0462     // Fermi-Dirac Function
0463     {[]() { return i18n("Complete Fermi-Dirac integral with index -1"); }, "Fm1", gsl_sf_fermi_dirac_m1, 1, nullptr, FunctionGroups::FermiDiracFunction},
0464     {[]() { return i18n("Complete Fermi-Dirac integral with index 0"); }, "F0", gsl_sf_fermi_dirac_0, 1, nullptr, FunctionGroups::FermiDiracFunction},
0465     {[]() { return i18n("Complete Fermi-Dirac integral with index 1"); }, "F1", gsl_sf_fermi_dirac_1, 1, nullptr, FunctionGroups::FermiDiracFunction},
0466     {[]() { return i18n("Complete Fermi-Dirac integral with index 2"); }, "F2", gsl_sf_fermi_dirac_2, 1, nullptr, FunctionGroups::FermiDiracFunction},
0467     {[]() { return i18n("Complete Fermi-Dirac integral with integer index j"); }, "Fj", nsl_sf_fermi_dirac_int, 2, nullptr, FunctionGroups::FermiDiracFunction},
0468     {[]() { return i18n("Complete Fermi-Dirac integral with index -1/2"); }, "Fmhalf", gsl_sf_fermi_dirac_mhalf, 1, nullptr, FunctionGroups::FermiDiracFunction},
0469     {[]() { return i18n("Complete Fermi-Dirac integral with index 1/2"); }, "Fhalf", gsl_sf_fermi_dirac_half, 1, nullptr, FunctionGroups::FermiDiracFunction},
0470     {[]() { return i18n("Complete Fermi-Dirac integral with index 3/2"); }, "F3half", gsl_sf_fermi_dirac_3half, 1, nullptr, FunctionGroups::FermiDiracFunction},
0471     {[]() { return i18n("Incomplete Fermi-Dirac integral with index zero"); }, "Finc0", gsl_sf_fermi_dirac_inc_0, 2, nullptr, FunctionGroups::FermiDiracFunction},
0472 
0473     // Gamma and Beta Functions
0474     {[]() { return i18n("Gamma function"); }, "gamma", gsl_sf_gamma, 1, nullptr, FunctionGroups::GammaAndBetaFunctions},
0475     {[]() { return i18n("Gamma function"); }, "tgamma", gsl_sf_gamma, 1, nullptr, FunctionGroups::GammaAndBetaFunctions},
0476     {[]() { return i18n("Logarithm of the gamma function"); }, "lgamma", gsl_sf_lngamma, 1, nullptr, FunctionGroups::GammaAndBetaFunctions},
0477     {[]() { return i18n("Logarithm naturalis of the gamma function"); }, "lngamma", gsl_sf_lngamma, 1, nullptr, FunctionGroups::GammaAndBetaFunctions},
0478     {[]() { return i18n("Regulated gamma function"); }, "gammastar", gsl_sf_gammastar, 1, nullptr, FunctionGroups::GammaAndBetaFunctions},
0479     {[]() { return i18n("Reciprocal of the gamma function"); }, "gammainv", gsl_sf_gammainv, 1, nullptr, FunctionGroups::GammaAndBetaFunctions},
0480     {[]() { return i18n("Factorial n!"); }, "fact", nsl_sf_fact, 1, nullptr, FunctionGroups::GammaAndBetaFunctions},
0481     {[]() { return i18n("Double factorial n!!"); }, "doublefact", nsl_sf_doublefact, 1, nullptr, FunctionGroups::GammaAndBetaFunctions},
0482     {[]() { return i18n("Logarithm of the factorial"); }, "lnfact", nsl_sf_lnfact, 1, nullptr, FunctionGroups::GammaAndBetaFunctions},
0483     {[]() { return i18n("Logarithm of the double factorial"); }, "lndoublefact", nsl_sf_lndoublefact, 1, nullptr, FunctionGroups::GammaAndBetaFunctions},
0484 
0485     {[]() { return i18n("Combinatorial factor"); }, "choose", nsl_sf_choose, 2, nullptr, FunctionGroups::GammaAndBetaFunctions},
0486     {[]() { return i18n("Logarithm of the combinatorial factor"); }, "lnchoose", nsl_sf_lnchoose, 2, nullptr, FunctionGroups::GammaAndBetaFunctions},
0487     {[]() { return i18n("Taylor coefficient"); }, "taylor", nsl_sf_taylorcoeff, 2, nullptr, FunctionGroups::GammaAndBetaFunctions},
0488     {[]() { return i18n("Pochhammer symbol"); }, "poch", gsl_sf_poch, 2, nullptr, FunctionGroups::GammaAndBetaFunctions},
0489     {[]() { return i18n("Logarithm of the Pochhammer symbol"); }, "lnpoch", gsl_sf_lnpoch, 2, nullptr, FunctionGroups::GammaAndBetaFunctions},
0490     {[]() { return i18n("Relative Pochhammer symbol"); }, "pochrel", gsl_sf_pochrel, 2, nullptr, FunctionGroups::GammaAndBetaFunctions},
0491     {[]() { return i18n("Unnormalized incomplete gamma function"); }, "gammainc", gsl_sf_gamma_inc, 2, nullptr, FunctionGroups::GammaAndBetaFunctions},
0492     {[]() { return i18n("Normalized incomplete gamma function"); }, "gammaincQ", gsl_sf_gamma_inc_Q, 2, nullptr, FunctionGroups::GammaAndBetaFunctions},
0493     {[]() { return i18n("Complementary normalized incomplete gamma function"); }, "gammaincP", gsl_sf_gamma_inc_P, 2, nullptr, FunctionGroups::GammaAndBetaFunctions},
0494     {[]() { return i18n("Beta function"); }, "beta", gsl_sf_beta, 2, nullptr, FunctionGroups::GammaAndBetaFunctions},
0495 
0496     {[]() { return i18n("Logarithm of the beta function"); }, "lnbeta", gsl_sf_lnbeta, 2, nullptr, FunctionGroups::GammaAndBetaFunctions},
0497     {[]() { return i18n("Normalized incomplete beta function"); }, "betainc", gsl_sf_beta_inc, 3, nullptr, FunctionGroups::GammaAndBetaFunctions},
0498 
0499     // Gegenbauer Functions
0500     {[]() { return i18n("Gegenbauer polynomial C_1"); }, "C1", gsl_sf_gegenpoly_1, 2, nullptr, FunctionGroups::GegenbauerFunctions},
0501     {[]() { return i18n("Gegenbauer polynomial C_2"); }, "C2", gsl_sf_gegenpoly_2, 2, nullptr, FunctionGroups::GegenbauerFunctions},
0502     {[]() { return i18n("Gegenbauer polynomial C_3"); }, "C3", gsl_sf_gegenpoly_3, 2, nullptr, FunctionGroups::GegenbauerFunctions},
0503     {[]() { return i18n("Gegenbauer polynomial C_n"); }, "Cn", nsl_sf_gegenpoly_n, 3, nullptr, FunctionGroups::GegenbauerFunctions},
0504 
0505 #if (GSL_MAJOR_VERSION > 2) || (GSL_MAJOR_VERSION == 2) && (GSL_MINOR_VERSION >= 4)
0506     // Hermite Polynomials and Functions
0507     {[]() { return i18n("Hermite polynomials physicists version"); }, "Hn", nsl_sf_hermite, 2, nullptr, FunctionGroups::HermitePolynomialsAndFunctions},
0508     {[]() { return i18n("Hermite polynomials probabilists version"); }, "Hen", nsl_sf_hermite_prob, 2, nullptr, FunctionGroups::HermitePolynomialsAndFunctions},
0509     {[]() { return i18n("Hermite functions"); }, "Hfn", nsl_sf_hermite_func, 2, nullptr, FunctionGroups::HermitePolynomialsAndFunctions},
0510 #if (GSL_MAJOR_VERSION > 2) || (GSL_MAJOR_VERSION == 2) && (GSL_MINOR_VERSION >= 6)
0511     {[]() { return i18n("Hermite functions (fast version)"); }, "Hfnf", nsl_sf_hermite_func_fast, 2, nullptr, FunctionGroups::HermitePolynomialsAndFunctions},
0512 #endif
0513     {[]() { return i18n("Derivatives of Hermite polynomials physicists version"); }, "Hnd", nsl_sf_hermite_deriv, 3, nullptr, FunctionGroups::HermitePolynomialsAndFunctions},
0514     {[]() { return i18n("Derivatives of Hermite polynomials probabilists version"); }, "Hend", nsl_sf_hermite_prob_deriv, 3, nullptr, FunctionGroups::HermitePolynomialsAndFunctions},
0515     {[]() { return i18n("Derivatives of Hermite functions"); }, "Hfnd", nsl_sf_hermite_func_der, 3, nullptr, FunctionGroups::HermitePolynomialsAndFunctions},
0516 #endif
0517 
0518     // Hypergeometric Functions
0519     {[]() { return i18n("Hypergeometric function 0F1"); }, "hyperg_0F1", gsl_sf_hyperg_0F1, 2, nullptr, FunctionGroups::HypergeometricFunctions},
0520     {[]() { return i18n("Confluent hypergeometric function 1F1 for integer parameters"); }, "hyperg_1F1i", nsl_sf_hyperg_1F1i, 3, nullptr, FunctionGroups::HypergeometricFunctions},
0521     {[]() { return i18n("Confluent hypergeometric function 1F1 for general parameters"); }, "hyperg_1F1", gsl_sf_hyperg_1F1, 3, nullptr, FunctionGroups::HypergeometricFunctions},
0522     {[]() { return i18n("Confluent hypergeometric function U for integer parameters"); }, "hyperg_Ui", nsl_sf_hyperg_Ui, 3, nullptr, FunctionGroups::HypergeometricFunctions},
0523     {[]() { return i18n("Confluent hypergeometric function U"); }, "hyperg_U", gsl_sf_hyperg_U, 3, nullptr, FunctionGroups::HypergeometricFunctions},
0524     {[]() { return i18n("Gauss hypergeometric function 2F1"); }, "hyperg_2F1", gsl_sf_hyperg_2F1, 4, nullptr, FunctionGroups::HypergeometricFunctions},
0525     {[]() { return i18n("Gauss hypergeometric function 2F1 with complex parameters"); }, "hyperg_2F1c", gsl_sf_hyperg_2F1_conj, 4, nullptr, FunctionGroups::HypergeometricFunctions},
0526     {[]() { return i18n("Renormalized Gauss hypergeometric function 2F1"); }, "hyperg_2F1r", gsl_sf_hyperg_2F1_renorm, 4, nullptr, FunctionGroups::HypergeometricFunctions},
0527     {[]() { return i18n("Renormalized Gauss hypergeometric function 2F1 with complex parameters"); }, "hyperg_2F1cr", gsl_sf_hyperg_2F1_conj_renorm, 4, nullptr, FunctionGroups::HypergeometricFunctions},
0528     {[]() { return i18n("Hypergeometric function 2F0"); }, "hyperg_2F0", gsl_sf_hyperg_2F0, 3, nullptr, FunctionGroups::HypergeometricFunctions},
0529 
0530     // Laguerre Functions
0531     {[]() { return i18n("generalized Laguerre polynomials L_1"); }, "L1", gsl_sf_laguerre_1, 2, nullptr, FunctionGroups::LaguerreFunctions},
0532     {[]() { return i18n("generalized Laguerre polynomials L_2"); }, "L2", gsl_sf_laguerre_2, 2, nullptr, FunctionGroups::LaguerreFunctions},
0533     {[]() { return i18n("generalized Laguerre polynomials L_3"); }, "L3", gsl_sf_laguerre_3, 2, nullptr, FunctionGroups::LaguerreFunctions},
0534     {[]() { return i18n("generalized Laguerre polynomials L_n"); }, "Ln", nsl_sf_laguerre_n, 3, nullptr, FunctionGroups::LaguerreFunctions},
0535 
0536     // Lambert W Functions
0537     {[]() { return i18n("Principal branch of the Lambert W function"); }, "W0", gsl_sf_lambert_W0, 1, nullptr, FunctionGroups::LambertWFunctions},
0538     {[]() { return i18n("Secondary real-valued branch of the Lambert W function"); }, "Wm1", gsl_sf_lambert_Wm1, 1, nullptr, FunctionGroups::LambertWFunctions},
0539 
0540     // Legendre Functions and Spherical Harmonics
0541     {[]() { return i18n("Legendre polynomial P_1"); }, "P1", gsl_sf_legendre_P1, 1, nullptr, FunctionGroups::LegendreFunctionsAndSphericalHarmonics},
0542     {[]() { return i18n("Legendre polynomial P_2"); }, "P2", gsl_sf_legendre_P2, 1, nullptr, FunctionGroups::LegendreFunctionsAndSphericalHarmonics},
0543     {[]() { return i18n("Legendre polynomial P_3"); }, "P3", gsl_sf_legendre_P3, 1, nullptr, FunctionGroups::LegendreFunctionsAndSphericalHarmonics},
0544     {[]() { return i18n("Legendre polynomial P_l"); }, "Pl", nsl_sf_legendre_Pl, 2, nullptr, FunctionGroups::LegendreFunctionsAndSphericalHarmonics},
0545     {[]() { return i18n("Legendre function Q_0"); }, "Q0", gsl_sf_legendre_Q0, 1, nullptr, FunctionGroups::LegendreFunctionsAndSphericalHarmonics},
0546     {[]() { return i18n("Legendre function Q_1"); }, "Q1", gsl_sf_legendre_Q1, 1, nullptr, FunctionGroups::LegendreFunctionsAndSphericalHarmonics},
0547     {[]() { return i18n("Legendre function Q_l"); }, "Ql", nsl_sf_legendre_Ql, 2, nullptr, FunctionGroups::LegendreFunctionsAndSphericalHarmonics},
0548     {[]() { return i18n("Associated Legendre polynomial"); }, "Plm", nsl_sf_legendre_Plm, 3, nullptr, FunctionGroups::LegendreFunctionsAndSphericalHarmonics},
0549     {[]() { return i18n("Normalized associated Legendre polynomial"); }, "Pslm", nsl_sf_legendre_sphPlm, 3, nullptr, FunctionGroups::LegendreFunctionsAndSphericalHarmonics},
0550     {[]() { return i18n("Irregular spherical conical function P^1/2"); }, "Phalf", gsl_sf_conicalP_half, 2, nullptr, FunctionGroups::LegendreFunctionsAndSphericalHarmonics},
0551 
0552     {[]() { return i18n("Regular spherical conical function P^(-1/2)"); }, "Pmhalf", gsl_sf_conicalP_mhalf, 2, nullptr, FunctionGroups::LegendreFunctionsAndSphericalHarmonics},
0553     {[]() { return i18n("Conical function P^0"); }, "Pc0", gsl_sf_conicalP_0, 2, nullptr, FunctionGroups::LegendreFunctionsAndSphericalHarmonics},
0554     {[]() { return i18n("Conical function P^1"); }, "Pc1", gsl_sf_conicalP_1, 2, nullptr, FunctionGroups::LegendreFunctionsAndSphericalHarmonics},
0555     {[]() { return i18n("Regular spherical conical function P^(-1/2-l)"); }, "Psr", nsl_sf_conicalP_sphreg, 3, nullptr, FunctionGroups::LegendreFunctionsAndSphericalHarmonics},
0556     {[]() { return i18n("Regular cylindrical conical function P^(-m)"); }, "Pcr", nsl_sf_conicalP_cylreg, 3, nullptr, FunctionGroups::LegendreFunctionsAndSphericalHarmonics},
0557     {[]() { return i18n("Zeroth radial eigenfunction of the Laplacian on the 3-dimensional hyperbolic space"); }, "H3d0", gsl_sf_legendre_H3d_0, 2, nullptr, FunctionGroups::LegendreFunctionsAndSphericalHarmonics},
0558     {[]() { return i18n("First radial eigenfunction of the Laplacian on the 3-dimensional hyperbolic space"); }, "H3d1", gsl_sf_legendre_H3d_1, 2, nullptr, FunctionGroups::LegendreFunctionsAndSphericalHarmonics},
0559     {[]() { return i18n("l-th radial eigenfunction of the Laplacian on the 3-dimensional hyperbolic space"); }, "H3d", nsl_sf_legendre_H3d, 3, nullptr, FunctionGroups::LegendreFunctionsAndSphericalHarmonics},
0560 
0561     // Logarithm and Related Functions
0562     {[]() { return i18n("Logarithm"); }, "log", gsl_sf_log, 1, nullptr, FunctionGroups::LogarithmAndRelatedFunctions},
0563     {[]() { return i18n("Base 2 logarithm"); }, "log2", static_cast<double (*)(double)>(&log2), 1, nullptr, FunctionGroups::LogarithmAndRelatedFunctions},
0564     {[]() { return i18n("Logarithm of the magnitude"); }, "logabs", gsl_sf_log_abs, 1, nullptr, FunctionGroups::LogarithmAndRelatedFunctions},
0565     {[]() { return QStringLiteral("log(1+x)"); }, "logp", gsl_sf_log_1plusx, 1, nullptr, FunctionGroups::LogarithmAndRelatedFunctions},
0566     {[]() { return QStringLiteral("log(1+x) - x"); }, "logpm", gsl_sf_log_1plusx_mx, 1, nullptr, FunctionGroups::LogarithmAndRelatedFunctions},
0567 
0568 #if (GSL_MAJOR_VERSION >= 2)
0569     // Mathieu Functions
0570     {[]() { return i18n("Characteristic values a_n(q) of the Mathieu functions ce_n(q, x)"); }, "an", nsl_sf_mathieu_a, 2, nullptr, FunctionGroups::MathieuFunctions},
0571     {[]() { return i18n("Characteristic values b_n(q) of the Mathieu functions se_n(q, x)"); }, "bn", nsl_sf_mathieu_b, 2, nullptr, FunctionGroups::MathieuFunctions},
0572     {[]() { return i18n("Angular Mathieu functions ce_n(q, x)"); }, "ce", nsl_sf_mathieu_ce, 3, nullptr, FunctionGroups::MathieuFunctions},
0573     {[]() { return i18n("Angular Mathieu functions se_n(q, x)"); }, "se", nsl_sf_mathieu_se, 3, nullptr, FunctionGroups::MathieuFunctions},
0574     {[]() { return i18n("Radial j-th kind Mathieu functions Mc_n^{(j)}(q, x)"); }, "Mc", nsl_sf_mathieu_Mc, 4, nsl_sf_mathieuParameterNames, FunctionGroups::MathieuFunctions},
0575     {[]() { return i18n("Radial j-th kind Mathieu functions Ms_n^{(j)}(q, x)"); }, "Ms", nsl_sf_mathieu_Ms, 4, nsl_sf_mathieuParameterNames, FunctionGroups::MathieuFunctions},
0576 #endif
0577 
0578     // Power Function
0579     {[]() { return i18n("x^n for integer n with an error estimate"); }, "gsl_powint", nsl_sf_powint, 2, nullptr, FunctionGroups::PowerFunction},
0580 
0581     // Psi (Digamma) Function
0582     {[]() { return i18n("Digamma function for positive integer n"); }, "psiint", nsl_sf_psiint, 1, nullptr, FunctionGroups::PsiDigammaFunction},
0583     {[]() { return i18n("Digamma function"); }, "psi", gsl_sf_psi, 1, nullptr, FunctionGroups::PsiDigammaFunction},
0584     {[]() { return i18n("Real part of the digamma function on the line 1+i y"); }, "psi1piy", gsl_sf_psi_1piy, 1, nullptr, FunctionGroups::PsiDigammaFunction},
0585     {[]() { return i18n("Trigamma function psi' for positive integer n"); }, "psi1int", nsl_sf_psi1int, 1, nullptr, FunctionGroups::PsiDigammaFunction},
0586     {[]() { return i18n("Trigamma function psi'"); }, "psi1", gsl_sf_psi_1, 1, nullptr, FunctionGroups::PsiDigammaFunction},
0587     {[]() { return i18n("Polygamma function psi^(n)"); }, "psin", nsl_sf_psin, 2, nullptr, FunctionGroups::PsiDigammaFunction},
0588 
0589     // Synchrotron Functions
0590     {[]() { return i18n("First synchrotron function"); }, "synchrotron1", gsl_sf_synchrotron_1, 1, nullptr, FunctionGroups::SynchrotronFunctions},
0591     {[]() { return i18n("Second synchrotron function"); }, "synchrotron2", gsl_sf_synchrotron_2, 1, nullptr, FunctionGroups::SynchrotronFunctions},
0592 
0593     // Transport Functions
0594     {[]() { return i18n("Transport function"); }, "J2", gsl_sf_transport_2, 1, nullptr, FunctionGroups::TransportFunctions},
0595     {[]() { return i18n("Transport function"); }, "J3", gsl_sf_transport_3, 1, nullptr, FunctionGroups::TransportFunctions},
0596     {[]() { return i18n("Transport function"); }, "J4", gsl_sf_transport_4, 1, nullptr, FunctionGroups::TransportFunctions},
0597     {[]() { return i18n("Transport function"); }, "J5", gsl_sf_transport_5, 1, nullptr, FunctionGroups::TransportFunctions},
0598 
0599     // Trigonometric Functions
0600     {[]() { return i18n("Sine"); }, "sin", gsl_sf_sin, 1, nullptr, FunctionGroups::TrigonometricFunctions},
0601     {[]() { return i18n("Cosine"); }, "cos", gsl_sf_cos, 1, nullptr, FunctionGroups::TrigonometricFunctions},
0602     {[]() { return i18n("Tangent"); }, "tan", static_cast<double (*)(double)>(&tan), 1, nullptr, FunctionGroups::TrigonometricFunctions},
0603     {[]() { return i18n("Inverse sine"); }, "asin", static_cast<double (*)(double)>(&asin), 1, nullptr, FunctionGroups::TrigonometricFunctions},
0604     {[]() { return i18n("Inverse cosine"); }, "acos", static_cast<double (*)(double)>(&acos), 1, nullptr, FunctionGroups::TrigonometricFunctions},
0605     {[]() { return i18n("Inverse tangent"); }, "atan", static_cast<double (*)(double)>(&atan), 1, nullptr, FunctionGroups::TrigonometricFunctions},
0606     {[]() { return i18n("Inverse tangent using sign"); }, "atan2", static_cast<double (*)(double, double)>(&atan2), 2, nullptr, FunctionGroups::TrigonometricFunctions},
0607     {[]() { return i18n("Hyperbolic sine"); }, "sinh", static_cast<double (*)(double)>(&sinh), 1, nullptr, FunctionGroups::TrigonometricFunctions},
0608     {[]() { return i18n("Hyperbolic cosine"); }, "cosh", static_cast<double (*)(double)>(&cosh), 1, nullptr, FunctionGroups::TrigonometricFunctions},
0609     {[]() { return i18n("Hyperbolic tangent"); }, "tanh", static_cast<double (*)(double)>(&tanh), 1, nullptr, FunctionGroups::TrigonometricFunctions},
0610     {[]() { return i18n("Inverse hyperbolic cosine"); }, "acosh", gsl_acosh, 1, nullptr, FunctionGroups::TrigonometricFunctions},
0611     {[]() { return i18n("Inverse hyperbolic sine"); }, "asinh", gsl_asinh, 1, nullptr, FunctionGroups::TrigonometricFunctions},
0612     {[]() { return i18n("Inverse hyperbolic tangent"); }, "atanh", gsl_atanh, 1, nullptr, FunctionGroups::TrigonometricFunctions},
0613     {[]() { return i18n("Secant"); }, "sec", nsl_sf_sec, 1, nullptr, FunctionGroups::TrigonometricFunctions},
0614     {[]() { return i18n("Cosecant"); }, "csc", nsl_sf_csc, 1, nullptr, FunctionGroups::TrigonometricFunctions},
0615     {[]() { return i18n("Cotangent"); }, "cot", nsl_sf_cot, 1, nullptr, FunctionGroups::TrigonometricFunctions},
0616     {[]() { return i18n("Inverse secant"); }, "asec", nsl_sf_asec, 1, nullptr, FunctionGroups::TrigonometricFunctions},
0617     {[]() { return i18n("Inverse cosecant"); }, "acsc", nsl_sf_acsc, 1, nullptr, FunctionGroups::TrigonometricFunctions},
0618     {[]() { return i18n("Inverse cotangent"); }, "acot", nsl_sf_acot, 1, nullptr, FunctionGroups::TrigonometricFunctions},
0619     {[]() { return i18n("Hyperbolic secant"); }, "sech", nsl_sf_sech, 1, nullptr, FunctionGroups::TrigonometricFunctions},
0620     {[]() { return i18n("Hyperbolic cosecant"); }, "csch", nsl_sf_csch, 1, nullptr, FunctionGroups::TrigonometricFunctions},
0621     {[]() { return i18n("Hyperbolic cotangent"); }, "coth", nsl_sf_coth, 1, nullptr, FunctionGroups::TrigonometricFunctions},
0622     {[]() { return i18n("Inverse hyperbolic secant"); }, "asech", nsl_sf_asech, 1, nullptr, FunctionGroups::TrigonometricFunctions},
0623     {[]() { return i18n("Inverse hyperbolic cosecant"); }, "acsch", nsl_sf_acsch, 1, nullptr, FunctionGroups::TrigonometricFunctions},
0624     {[]() { return i18n("Inverse hyperbolic cotangent"); }, "acoth", nsl_sf_acoth, 1, nullptr, FunctionGroups::TrigonometricFunctions},
0625     {[]() { return i18n("Sinc function sin(x)/x"); }, "sinc", gsl_sf_sinc, 1, nullptr, FunctionGroups::TrigonometricFunctions},
0626     {[]() { return QStringLiteral("log(sinh(x))"); }, "logsinh", gsl_sf_lnsinh, 1, nullptr, FunctionGroups::TrigonometricFunctions},
0627     {[]() { return QStringLiteral("log(cosh(x))"); }, "logcosh", gsl_sf_lncosh, 1, nullptr, FunctionGroups::TrigonometricFunctions},
0628     {[]() { return i18n("Hypotenuse function"); }, "hypot", gsl_sf_hypot, 2, nullptr, FunctionGroups::TrigonometricFunctions},
0629     {[]() { return i18n("Three component hypotenuse function"); }, "hypot3", gsl_hypot3, 3, nullptr, FunctionGroups::TrigonometricFunctions},
0630     {[]() { return i18n("restrict to [-pi, pi]"); }, "anglesymm", gsl_sf_angle_restrict_symm, 1, nullptr, FunctionGroups::TrigonometricFunctions},
0631     {[]() { return i18n("restrict to [0, 2 pi]"); }, "anglepos", gsl_sf_angle_restrict_pos, 1, nullptr, FunctionGroups::TrigonometricFunctions},
0632 
0633     // Zeta Functions
0634     {[]() { return i18n("Riemann zeta function for integer n"); }, "zetaint", nsl_sf_zetaint, 1, nullptr, FunctionGroups::ZetaFunctions},
0635     {[]() { return i18n("Riemann zeta function"); }, "zeta", gsl_sf_zeta, 1, nullptr, FunctionGroups::ZetaFunctions},
0636     {[]() { return i18n("zeta(n)-1 for integer n"); }, "zetam1int", nsl_sf_zetam1int, 1, nullptr, FunctionGroups::ZetaFunctions},
0637     {[]() { return i18n("zeta(x)-1"); }, "zetam1", gsl_sf_zetam1, 1, nullptr, FunctionGroups::ZetaFunctions},
0638     {[]() { return i18n("Hurwitz zeta function"); }, "hzeta", gsl_sf_hzeta, 2, nullptr, FunctionGroups::ZetaFunctions},
0639     {[]() { return i18n("Eta function for integer n"); }, "etaint", nsl_sf_etaint, 1, nullptr, FunctionGroups::ZetaFunctions},
0640     {[]() { return i18n("Eta function"); }, "eta", gsl_sf_eta, 1, nullptr, FunctionGroups::ZetaFunctions},
0641 
0642     // GSL Random Number Generators: see https://www.gnu.org/software/gsl/doc/html/randist.html
0643     // Random number generator
0644     {[]() { return i18n("Gaussian random numbers"); }, "randgaussian", nsl_sf_ran_gaussian, 1, nullptr, FunctionGroups::RandomNumberGenerator},
0645     {[]() { return i18n("Exponential random numbers"); }, "randexponential", nsl_sf_ran_exponential, 1, nullptr, FunctionGroups::RandomNumberGenerator},
0646     {[]() { return i18n("Laplacian random numbers"); }, "randlaplace", nsl_sf_ran_laplace, 1, nullptr, FunctionGroups::RandomNumberGenerator},
0647     {[]() { return i18n("Cauchy/Lorentz random numbers"); }, "randcauchy", nsl_sf_ran_cauchy, 1, nullptr, FunctionGroups::RandomNumberGenerator},
0648     {[]() { return i18n("Rayleigh random numbers"); }, "randrayleigh", nsl_sf_ran_rayleigh, 1, nullptr, FunctionGroups::RandomNumberGenerator},
0649     {[]() { return i18n("Landau random numbers"); }, "randlandau", nsl_sf_ran_landau, 0, nullptr, FunctionGroups::RandomNumberGenerator},
0650     {[]() { return i18n("Levy alpha-stable random numbers"); }, "randlevy", nsl_sf_ran_levy, 2, nullptr, FunctionGroups::RandomNumberGenerator},
0651     {[]() { return i18n("Gamma random numbers"); }, "randgamma", nsl_sf_ran_gamma, 2, nullptr, FunctionGroups::RandomNumberGenerator},
0652     {[]() { return i18n("Flat random numbers"); }, "randflat", nsl_sf_ran_flat, 2, nullptr, FunctionGroups::RandomNumberGenerator},
0653     {[]() { return i18n("Lognormal random numbers"); }, "randlognormal", nsl_sf_ran_lognormal, 2, nullptr, FunctionGroups::RandomNumberGenerator},
0654 
0655     {[]() { return i18n("Chi-squared random numbers"); }, "randchisq", nsl_sf_ran_chisq, 1, nullptr, FunctionGroups::RandomNumberGenerator},
0656     {[]() { return i18n("t-distributed random numbers"); }, "randtdist", nsl_sf_ran_tdist, 1, nullptr, FunctionGroups::RandomNumberGenerator},
0657     {[]() { return i18n("Logistic random numbers"); }, "randlogistic", nsl_sf_ran_logistic, 1, nullptr, FunctionGroups::RandomNumberGenerator},
0658     {[]() { return i18n("Poisson random numbers"); }, "randpoisson", nsl_sf_ran_poisson, 1, nullptr, FunctionGroups::RandomNumberGenerator},
0659     {[]() { return i18n("Bernoulli random numbers"); }, "randbernoulli", nsl_sf_ran_bernoulli, 1, nullptr, FunctionGroups::RandomNumberGenerator},
0660     {[]() { return i18n("Binomial random numbers"); }, "randbinomial", nsl_sf_ran_binomial, 2, nullptr, FunctionGroups::RandomNumberGenerator},
0661 
0662     // GSL Random Number Distributions: see https://www.gnu.org/software/gsl/doc/html/randist.html
0663     // Gaussian Distribution
0664     {[]() { return i18n("Probability density for a Gaussian distribution"); }, "gaussian", gsl_ran_gaussian_pdf, 2, nullptr, FunctionGroups::GaussianDistribution},
0665     {[]() { return i18n("Probability density for a unit Gaussian distribution"); }, "ugaussian", gsl_ran_ugaussian_pdf, 1, nullptr, FunctionGroups::GaussianDistribution},
0666     {[]() { return i18n("Cumulative distribution function P"); }, "gaussianP", gsl_cdf_gaussian_P, 2, nullptr, FunctionGroups::GaussianDistribution},
0667     {[]() { return i18n("Cumulative distribution function Q"); }, "gaussianQ", gsl_cdf_gaussian_Q, 2, nullptr, FunctionGroups::GaussianDistribution},
0668     {[]() { return i18n("Inverse cumulative distribution function P"); }, "gaussianPinv", gsl_cdf_gaussian_Pinv, 2, nullptr, FunctionGroups::GaussianDistribution},
0669     {[]() { return i18n("Inverse cumulative distribution function Q"); }, "gaussianQinv", gsl_cdf_gaussian_Qinv, 2, nullptr, FunctionGroups::GaussianDistribution},
0670     {[]() { return i18n("Cumulative unit distribution function P"); }, "ugaussianP", gsl_cdf_ugaussian_P, 1, nullptr, FunctionGroups::GaussianDistribution},
0671     {[]() { return i18n("Cumulative unit distribution function Q"); }, "ugaussianQ", gsl_cdf_ugaussian_Q, 1, nullptr, FunctionGroups::GaussianDistribution},
0672     {[]() { return i18n("Inverse cumulative unit distribution function P"); }, "ugaussianPinv", gsl_cdf_ugaussian_Pinv, 1, nullptr, FunctionGroups::GaussianDistribution},
0673     {[]() { return i18n("Inverse cumulative unit distribution function Q"); }, "ugaussianQinv", gsl_cdf_ugaussian_Qinv, 1, nullptr, FunctionGroups::GaussianDistribution},
0674 
0675     {[]() { return i18n("Probability density for Gaussian tail distribution"); }, "gaussiantail", gsl_ran_gaussian_tail_pdf, 3, nullptr, FunctionGroups::GaussianDistribution},
0676     {[]() { return i18n("Probability density for unit Gaussian tail distribution"); }, "ugaussiantail", gsl_ran_ugaussian_tail_pdf, 2, nullptr, FunctionGroups::GaussianDistribution},
0677     {[]() { return i18n("Probability density for a bivariate Gaussian distribution"); }, "gaussianbi", gsl_ran_bivariate_gaussian_pdf, 5, nullptr, FunctionGroups::GaussianDistribution},
0678 
0679     // Exponential Distribution
0680     {[]() { return i18n("Probability density for an exponential distribution"); }, "exponential", gsl_ran_exponential_pdf, 2, nullptr, FunctionGroups::ExponentialDistribution},
0681     {[]() { return i18n("Cumulative distribution function P"); }, "exponentialP", gsl_cdf_exponential_P, 2, nullptr, FunctionGroups::ExponentialDistribution},
0682     {[]() { return i18n("Cumulative distribution function Q"); }, "exponentialQ", gsl_cdf_exponential_Q, 2, nullptr, FunctionGroups::ExponentialDistribution},
0683     {[]() { return i18n("Inverse cumulative distribution function P"); }, "exponentialPinv", gsl_cdf_exponential_Pinv, 2, nullptr, FunctionGroups::ExponentialDistribution},
0684     {[]() { return i18n("Inverse cumulative distribution function Q"); }, "exponentialQinv", gsl_cdf_exponential_Qinv, 2, nullptr, FunctionGroups::ExponentialDistribution},
0685 
0686     // Laplace Distribution
0687     {[]() { return i18n("Probability density for a Laplace distribution"); }, "laplace", gsl_ran_laplace_pdf, 2, nullptr, FunctionGroups::LaplaceDistribution},
0688     {[]() { return i18n("Cumulative distribution function P"); }, "laplaceP", gsl_cdf_laplace_P, 2, nullptr, FunctionGroups::LaplaceDistribution},
0689     {[]() { return i18n("Cumulative distribution function Q"); }, "laplaceQ", gsl_cdf_laplace_Q, 2, nullptr, FunctionGroups::LaplaceDistribution},
0690     {[]() { return i18n("Inverse cumulative distribution function P"); }, "laplacePinv", gsl_cdf_laplace_Pinv, 2, nullptr, FunctionGroups::LaplaceDistribution},
0691     {[]() { return i18n("Inverse cumulative distribution function Q"); }, "laplaceQinv", gsl_cdf_laplace_Qinv, 2, nullptr, FunctionGroups::LaplaceDistribution},
0692 
0693     // Exponential Power Distribution
0694     {[]() { return i18n("Probability density for an exponential power distribution"); }, "exppow", gsl_ran_exppow_pdf, 3, nullptr, FunctionGroups::ExponentialPowerDistribution},
0695     {[]() { return i18n("cumulative distribution function P"); }, "exppowP", gsl_cdf_exppow_P, 3, nullptr, FunctionGroups::ExponentialPowerDistribution},
0696     {[]() { return i18n("Cumulative distribution function Q"); }, "exppowQ", gsl_cdf_exppow_Q, 3, nullptr, FunctionGroups::ExponentialPowerDistribution},
0697 
0698     // Cauchy Distribution
0699     {[]() { return i18n("Probability density for a Cauchy distribution"); }, "cauchy", gsl_ran_cauchy_pdf, 2, nullptr, FunctionGroups::CauchyDistribution},
0700     {[]() { return i18n("Cumulative distribution function P"); }, "cauchyP", gsl_cdf_cauchy_P, 2, nullptr, FunctionGroups::CauchyDistribution},
0701     {[]() { return i18n("Cumulative distribution function Q"); }, "cauchyQ", gsl_cdf_cauchy_Q, 2, nullptr, FunctionGroups::CauchyDistribution},
0702     {[]() { return i18n("Inverse cumulative distribution function P"); }, "cauchyPinv", gsl_cdf_cauchy_Pinv, 2, nullptr, FunctionGroups::CauchyDistribution},
0703     {[]() { return i18n("Inverse cumulative distribution function Q"); }, "cauchyQinv", gsl_cdf_cauchy_Qinv, 2, nullptr, FunctionGroups::CauchyDistribution},
0704 
0705     // Rayleigh Distribution
0706     {[]() { return i18n("Probability density for a Rayleigh distribution"); }, "rayleigh", gsl_ran_rayleigh_pdf, 2, nullptr, FunctionGroups::RayleighDistribution},
0707     {[]() { return i18n("Cumulative distribution function P"); }, "rayleighP", gsl_cdf_rayleigh_P, 2, nullptr, FunctionGroups::RayleighDistribution},
0708     {[]() { return i18n("Cumulative distribution function Q"); }, "rayleighQ", gsl_cdf_rayleigh_Q, 2, nullptr, FunctionGroups::RayleighDistribution},
0709     {[]() { return i18n("Inverse cumulative distribution function P"); }, "rayleighPinv", gsl_cdf_rayleigh_Pinv, 2, nullptr, FunctionGroups::RayleighDistribution},
0710     {[]() { return i18n("Inverse cumulative distribution function Q"); }, "rayleighQinv", gsl_cdf_rayleigh_Qinv, 2, nullptr, FunctionGroups::RayleighDistribution},
0711     {[]() { return i18n("Probability density for a Rayleigh tail distribution"); }, "rayleigh_tail", gsl_ran_rayleigh_tail_pdf, 3, nullptr, FunctionGroups::RayleighDistribution},
0712 
0713     // Landau Distribution
0714     {[]() { return i18n("Probability density for a Landau distribution"); }, "landau", gsl_ran_landau_pdf, 1, nullptr, FunctionGroups::LandauDistribution},
0715 
0716     // Gamma Distribution
0717     {[]() { return i18n("Probability density for a gamma distribution"); }, "gammapdf", gsl_ran_gamma_pdf, 3, nullptr, FunctionGroups::GammaDistribution},
0718     {[]() { return i18n("Cumulative distribution function P"); }, "gammaP", gsl_cdf_gamma_P, 3, nullptr, FunctionGroups::GammaDistribution},
0719     {[]() { return i18n("Cumulative distribution function Q"); }, "gammaQ", gsl_cdf_gamma_Q, 3, nullptr, FunctionGroups::GammaDistribution},
0720     {[]() { return i18n("Inverse cumulative distribution function P"); }, "gammaPinv", gsl_cdf_gamma_Pinv, 3, nullptr, FunctionGroups::GammaDistribution},
0721     {[]() { return i18n("Inverse cumulative distribution function Q"); }, "gammaQinv", gsl_cdf_gamma_Qinv, 3, nullptr, FunctionGroups::GammaDistribution},
0722 
0723     // Flat (Uniform) Distribution
0724     {[]() { return i18n("Probability density for a uniform distribution"); }, "flat", gsl_ran_flat_pdf, 3, nullptr, FunctionGroups::FlatUniformDistribution},
0725     {[]() { return i18n("Cumulative distribution function P"); }, "flatP", gsl_cdf_flat_P, 3, nullptr, FunctionGroups::FlatUniformDistribution},
0726     {[]() { return i18n("Cumulative distribution function Q"); }, "flatQ", gsl_cdf_flat_Q, 3, nullptr, FunctionGroups::FlatUniformDistribution},
0727     {[]() { return i18n("Inverse cumulative distribution function P"); }, "flatPinv", gsl_cdf_flat_Pinv, 3, nullptr, FunctionGroups::FlatUniformDistribution},
0728     {[]() { return i18n("Inverse cumulative distribution function Q"); }, "flatQinv", gsl_cdf_flat_Qinv, 3, nullptr, FunctionGroups::FlatUniformDistribution},
0729 
0730     // Lognormal Distribution
0731     {[]() { return i18n("Probability density for a lognormal distribution"); }, "lognormal", gsl_ran_lognormal_pdf, 3, nullptr, FunctionGroups::LognormalDistribution},
0732     {[]() { return i18n("Cumulative distribution function P"); }, "lognormalP", gsl_cdf_lognormal_P, 3, nullptr, FunctionGroups::LognormalDistribution},
0733     {[]() { return i18n("Cumulative distribution function Q"); }, "lognormalQ", gsl_cdf_lognormal_Q, 3, nullptr, FunctionGroups::LognormalDistribution},
0734     {[]() { return i18n("Inverse cumulative distribution function P"); }, "lognormalPinv", gsl_cdf_lognormal_Pinv, 3, nullptr, FunctionGroups::LognormalDistribution},
0735     {[]() { return i18n("Inverse cumulative distribution function Q"); }, "lognormalQinv", gsl_cdf_lognormal_Qinv, 3, nullptr, FunctionGroups::LognormalDistribution},
0736 
0737     // Chi-squared Distribution
0738     {[]() { return i18n("Probability density for a chi squared distribution"); }, "chisq", gsl_ran_chisq_pdf, 2, nullptr, FunctionGroups::ChisquaredDistribution},
0739     {[]() { return i18n("Cumulative distribution function P"); }, "chisqP", gsl_cdf_chisq_P, 2, nullptr, FunctionGroups::ChisquaredDistribution},
0740     {[]() { return i18n("Cumulative distribution function Q"); }, "chisqQ", gsl_cdf_chisq_Q, 2, nullptr, FunctionGroups::ChisquaredDistribution},
0741     {[]() { return i18n("Inverse cumulative distribution function P"); }, "chisqPinv", gsl_cdf_chisq_Pinv, 2, nullptr, FunctionGroups::ChisquaredDistribution},
0742     {[]() { return i18n("Inverse cumulative distribution function Q"); }, "chisqQinv", gsl_cdf_chisq_Qinv, 2, nullptr, FunctionGroups::ChisquaredDistribution},
0743 
0744     // F-distribution
0745     {[]() { return i18n("Probability density for a F-distribution"); }, "fdist", gsl_ran_fdist_pdf, 3, nullptr, FunctionGroups::Fdistribution},
0746     {[]() { return i18n("Cumulative distribution function P"); }, "fdistP", gsl_cdf_fdist_P, 3, nullptr, FunctionGroups::Fdistribution},
0747     {[]() { return i18n("Cumulative distribution function Q"); }, "fdistQ", gsl_cdf_fdist_Q, 3, nullptr, FunctionGroups::Fdistribution},
0748     {[]() { return i18n("Inverse cumulative distribution function P"); }, "fdistPinv", gsl_cdf_fdist_Pinv, 3, nullptr, FunctionGroups::Fdistribution},
0749     {[]() { return i18n("Inverse cumulative distribution function Q"); }, "fdistQinv", gsl_cdf_fdist_Qinv, 3, nullptr, FunctionGroups::Fdistribution},
0750 
0751     // t-distribution
0752     {[]() { return i18n("Probability density for a t-distribution"); }, "tdist", gsl_ran_tdist_pdf, 2, nullptr, FunctionGroups::Tdistribution},
0753     {[]() { return i18n("Cumulative distribution function P"); }, "tdistP", gsl_cdf_tdist_P, 2, nullptr, FunctionGroups::Tdistribution},
0754     {[]() { return i18n("Cumulative distribution function Q"); }, "tdistQ", gsl_cdf_tdist_Q, 2, nullptr, FunctionGroups::Tdistribution},
0755     {[]() { return i18n("Inverse cumulative distribution function P"); }, "tdistPinv", gsl_cdf_tdist_Pinv, 2, nullptr, FunctionGroups::Tdistribution},
0756     {[]() { return i18n("Inverse cumulative distribution function Q"); }, "tdistQinv", gsl_cdf_tdist_Qinv, 2, nullptr, FunctionGroups::Tdistribution},
0757 
0758     // Beta Distribution
0759     {[]() { return i18n("Probability density for a beta distribution"); }, "betapdf", gsl_ran_beta_pdf, 3, nullptr, FunctionGroups::BetaDistribution},
0760     {[]() { return i18n("Cumulative distribution function P"); }, "betaP", gsl_cdf_beta_P, 3, nullptr, FunctionGroups::BetaDistribution},
0761     {[]() { return i18n("Cumulative distribution function Q"); }, "betaQ", gsl_cdf_beta_Q, 3, nullptr, FunctionGroups::BetaDistribution},
0762     {[]() { return i18n("Inverse cumulative distribution function P"); }, "betaPinv", gsl_cdf_beta_Pinv, 3, nullptr, FunctionGroups::BetaDistribution},
0763     {[]() { return i18n("Inverse cumulative distribution function Q"); }, "betaQinv", gsl_cdf_beta_Qinv, 3, nullptr, FunctionGroups::BetaDistribution},
0764 
0765     // Logistic Distribution
0766     {[]() { return i18n("Probability density for a logistic distribution"); }, "logistic", gsl_ran_logistic_pdf, 2, nullptr, FunctionGroups::LogisticDistribution},
0767     {[]() { return i18n("Cumulative distribution function P"); }, "logisticP", gsl_cdf_logistic_P, 2, nullptr, FunctionGroups::LogisticDistribution},
0768     {[]() { return i18n("Cumulative distribution function Q"); }, "logisticQ", gsl_cdf_logistic_Q, 2, nullptr, FunctionGroups::LogisticDistribution},
0769     {[]() { return i18n("Inverse cumulative distribution function P"); }, "logisticPinv", gsl_cdf_logistic_Pinv, 2, nullptr, FunctionGroups::LogisticDistribution},
0770     {[]() { return i18n("Inverse cumulative distribution function Q"); }, "logisticQinv", gsl_cdf_logistic_Qinv, 2, nullptr, FunctionGroups::LogisticDistribution},
0771 
0772     // Pareto Distribution
0773     {[]() { return i18n("Probability density for a Pareto distribution"); }, "pareto", gsl_ran_pareto_pdf, 3, nullptr, FunctionGroups::ParetoDistribution},
0774     {[]() { return i18n("Cumulative distribution function P"); }, "paretoP", gsl_cdf_pareto_P, 3, nullptr, FunctionGroups::ParetoDistribution},
0775     {[]() { return i18n("Cumulative distribution function Q"); }, "paretoQ", gsl_cdf_pareto_Q, 3, nullptr, FunctionGroups::ParetoDistribution},
0776     {[]() { return i18n("Inverse cumulative distribution function P"); }, "paretoPinv", gsl_cdf_pareto_Pinv, 3, nullptr, FunctionGroups::ParetoDistribution},
0777     {[]() { return i18n("Inverse cumulative distribution function Q"); }, "paretoQinv", gsl_cdf_pareto_Qinv, 3, nullptr, FunctionGroups::ParetoDistribution},
0778 
0779     // Weibull Distribution
0780     {[]() { return i18n("Probability density for a Weibull distribution"); }, "weibull", gsl_ran_weibull_pdf, 3, nullptr, FunctionGroups::WeibullDistribution},
0781     {[]() { return i18n("Cumulative distribution function P"); }, "weibullP", gsl_cdf_weibull_P, 3, nullptr, FunctionGroups::WeibullDistribution},
0782     {[]() { return i18n("Cumulative distribution function Q"); }, "weibullQ", gsl_cdf_weibull_Q, 3, nullptr, FunctionGroups::WeibullDistribution},
0783     {[]() { return i18n("Inverse cumulative distribution function P"); }, "weibullPinv", gsl_cdf_weibull_Pinv, 3, nullptr, FunctionGroups::WeibullDistribution},
0784     {[]() { return i18n("Inverse cumulative distribution function Q"); }, "weibullQinv", gsl_cdf_weibull_Qinv, 3, nullptr, FunctionGroups::WeibullDistribution},
0785 
0786     // Gumbel Distribution
0787     {[]() { return i18n("Probability density for a Type-1 Gumbel distribution"); }, "gumbel1", gsl_ran_gumbel1_pdf, 3, nullptr, FunctionGroups::GumbelDistribution},
0788     {[]() { return i18n("Cumulative distribution function P"); }, "gumbel1P", gsl_cdf_gumbel1_P, 3, nullptr, FunctionGroups::GumbelDistribution},
0789     {[]() { return i18n("Cumulative distribution function Q"); }, "gumbel1Q", gsl_cdf_gumbel1_Q, 3, nullptr, FunctionGroups::GumbelDistribution},
0790     {[]() { return i18n("Inverse cumulative distribution function P"); }, "gumbel1Pinv", gsl_cdf_gumbel1_Pinv, 3, nullptr, FunctionGroups::GumbelDistribution},
0791     {[]() { return i18n("Inverse cumulative distribution function Q"); }, "gumbel1Qinv", gsl_cdf_gumbel1_Qinv, 3, nullptr, FunctionGroups::GumbelDistribution},
0792     {[]() { return i18n("Probability density for a Type-2 Gumbel distribution"); }, "gumbel2", gsl_ran_gumbel2_pdf, 3, nullptr, FunctionGroups::GumbelDistribution},
0793     {[]() { return i18n("Cumulative distribution function P"); }, "gumbel2P", gsl_cdf_gumbel2_P, 3, nullptr, FunctionGroups::GumbelDistribution},
0794     {[]() { return i18n("Cumulative distribution function Q"); }, "gumbel2Q", gsl_cdf_gumbel2_Q, 3, nullptr, FunctionGroups::GumbelDistribution},
0795     {[]() { return i18n("Inverse cumulative distribution function P"); }, "gumbel2Pinv", gsl_cdf_gumbel2_Pinv, 3, nullptr, FunctionGroups::GumbelDistribution},
0796     {[]() { return i18n("Inverse cumulative distribution function Q"); }, "gumbel2Qinv", gsl_cdf_gumbel2_Qinv, 3, nullptr, FunctionGroups::GumbelDistribution},
0797 
0798     // Poisson Distribution
0799     {[]() { return i18n("Probability density for a Poisson distribution"); }, "poisson", nsl_sf_poisson, 2, nullptr, FunctionGroups::PoissonDistribution},
0800     {[]() { return i18n("Cumulative distribution function P"); }, "poissonP", [](double v1, double v2) { return gsl_cdf_poisson_P(v1, v2); },  2, nullptr, FunctionGroups::PoissonDistribution},
0801     {[]() { return i18n("Cumulative distribution function Q"); }, "poissonQ", [](double v1, double v2) { return gsl_cdf_poisson_Q(v1, v2); },  2, nullptr, FunctionGroups::PoissonDistribution},
0802 
0803     // Bernoulli Distribution
0804     {[]() { return i18n("Probability density for a Bernoulli distribution"); }, "bernoulli", nsl_sf_bernoulli, 2, nullptr, FunctionGroups::BernoulliDistribution},
0805 
0806     // Binomial Distribution
0807     {[]() { return i18n("Probability density for a binomial distribution"); }, "binomial", nsl_sf_binomial, 3, nullptr, FunctionGroups::BinomialDistribution},
0808     {[]() { return i18n("Cumulative distribution function P"); }, "binomialP", gsl_cdf_binomial_P, 3, nullptr, FunctionGroups::BinomialDistribution},
0809     {[]() { return i18n("Cumulative distribution function Q"); }, "binomialQ", gsl_cdf_binomial_Q, 3, nullptr, FunctionGroups::BinomialDistribution},
0810     {[]() { return i18n("Probability density for a negative binomial distribution"); }, "negative_binomial", nsl_sf_negative_binomial, 3, nullptr, FunctionGroups::BinomialDistribution},
0811     {[]() { return i18n("Cumulative distribution function P"); }, "negative_binomialP", gsl_cdf_negative_binomial_P, 3, nullptr, FunctionGroups::BinomialDistribution},
0812     {[]() { return i18n("Cumulative distribution function Q"); }, "negative_binomialQ", gsl_cdf_negative_binomial_Q, 3, nullptr, FunctionGroups::BinomialDistribution},
0813 
0814     // Pascal Distribution
0815     {[]() { return i18n("Probability density for a Pascal distribution"); }, "pascal", nsl_sf_pascal, 3, nullptr, FunctionGroups::PascalDistribution},
0816     {[]() { return i18n("Cumulative distribution function P"); }, "pascalP", gsl_cdf_pascal_P, 3, nullptr, FunctionGroups::PascalDistribution},
0817     {[]() { return i18n("Cumulative distribution function Q"); }, "pascalQ", gsl_cdf_pascal_Q, 3, nullptr, FunctionGroups::PascalDistribution},
0818 
0819     // Geometric Distribution
0820     {[]() { return i18n("Probability density for a geometric distribution"); }, "geometric", nsl_sf_geometric, 2, nullptr, FunctionGroups::GeometricDistribution},
0821     {[]() { return i18n("Cumulative distribution function P"); }, "geometricP", gsl_cdf_geometric_P, 2, nullptr, FunctionGroups::GeometricDistribution},
0822     {[]() { return i18n("Cumulative distribution function Q"); }, "geometricQ", gsl_cdf_geometric_Q, 2, nullptr, FunctionGroups::GeometricDistribution},
0823 
0824     // Hypergeometric Distribution
0825     {[]() { return i18n("Probability density for a hypergeometric distribution"); }, "hypergeometric", nsl_sf_hypergeometric, 4, nullptr, FunctionGroups::HypergeometricDistribution},
0826     {[]() { return i18n("Cumulative distribution function P"); }, "hypergeometricP", gsl_cdf_hypergeometric_P, 4, nullptr, FunctionGroups::HypergeometricDistribution},
0827     {[]() { return i18n("Cumulative distribution function Q"); }, "hypergeometricQ", gsl_cdf_hypergeometric_Q, 4, nullptr, FunctionGroups::HypergeometricDistribution},
0828 
0829     // Logarithmic Distribution
0830     {[]() { return i18n("Probability density for a logarithmic distribution"); }, "logarithmic", nsl_sf_logarithmic, 2, nullptr, FunctionGroups::LogarithmicDistribution},
0831 };
0832 
0833 // clang-format on
0834 
0835 const int _number_functions = sizeof(_functions) / sizeof(funs);
0836 
0837 // ########################################################################
0838 // #### Function declarations ############################################
0839 // ########################################################################
0840 
0841 double greaterThan(const double v1, const double v2) {
0842     return v1 > v2;
0843 }
0844 
0845 double greaterEqualThan(const double v1, const double v2) {
0846     return v1 >= v2;
0847 }
0848 
0849 double lessThan(const double v1, const double v2) {
0850     return v1 < v2;
0851 }
0852 
0853 double lessEqualThan(const double v1, const double v2) {
0854     return v1 <= v2;
0855 }
0856 
0857 double equal(const double v1, const double v2) {
0858     return v1 == v2;
0859 }
0860 
0861 bool convertDoubleToBool(const double value) {
0862     return value != 0;
0863 }
0864 
0865 double ifCondition(const double condition, const double valueIfTrue, const double valueIfFalse) {
0866     if (convertDoubleToBool(condition))
0867         return valueIfTrue;
0868     return valueIfFalse;
0869 }
0870 
0871 double andFunction(const double v1, const double v2) {
0872     return (convertDoubleToBool(v1) && convertDoubleToBool(v2));
0873 }
0874 
0875 double orFunction(const double v1, const double v2) {
0876     return (convertDoubleToBool(v1) || convertDoubleToBool(v2));
0877 }
0878 
0879 double xorFunction(const double v1, const double v2) {
0880     if (convertDoubleToBool(v1) == convertDoubleToBool(v2))
0881         return 0;
0882     return 1;
0883 }
0884 
0885 double notFunction(const double v) {
0886     if (convertDoubleToBool(v))
0887         return 0;
0888     return 1;
0889 }
0890 
0891 double betweenIncluded(const double x, const double min, const double max) {
0892     if (x >= min && x <= max)
0893         return 1;
0894     return 0;
0895 }
0896 
0897 double outsideIncluded(const double x, const double min, const double max) {
0898     if (x <= min || x >= max)
0899         return 1;
0900     return 0;
0901 }
0902 
0903 double between(const double x, const double min, const double max) {
0904     if (x > min && x < max)
0905         return 1;
0906     return 0;
0907 }
0908 
0909 double outside(const double x, const double min, const double max) {
0910     if (x < min || x > max)
0911         return 1;
0912     return 0;
0913 }
0914 
0915 double equalEpsilon(const double v1, const double v2, const double epsilon) {
0916     if (fabs(v2 - v1) <= epsilon)
0917         return 1;
0918     return 0;
0919 }
0920 
0921 double roundn(const double v, const double precision) {
0922     return nsl_math_round_places(v, static_cast<int>(precision));
0923 }
0924 
0925 // ########################################################################
0926 // #### Parameter Functions ###############################################
0927 // ########################################################################
0928 
0929 QString parameterXE(int parameterIndex) {
0930     switch (parameterIndex) {
0931     case 0:
0932         return QStringLiteral("x");
0933     case 1:
0934         return QStringLiteral("e");
0935     }
0936     return i18n("Invalid");
0937 }
0938 
0939 QString ifParameterNames(int parameterIndex) {
0940     switch (parameterIndex) {
0941     case 0:
0942         return i18n("condition");
0943     case 1:
0944         return i18n("trueValue");
0945     case 2:
0946         return i18n("falseValue");
0947     }
0948     return i18n("Invalid");
0949 }
0950 
0951 QString nsl_sf_mathieuParameterNames(int parameterIndex) {
0952     switch (parameterIndex) {
0953     case 0:
0954         return i18n("n");
0955     case 1:
0956         return i18n("j");
0957     case 2:
0958         return i18n("q");
0959     case 3:
0960         return i18n("x");
0961     }
0962     return i18n("Invalid");
0963 }
0964 
0965 QString betweenOutsideParameterNames(int parameterIndex) {
0966     switch (parameterIndex) {
0967     case 0:
0968         return i18n("x");
0969     case 1:
0970         return i18n("min");
0971     case 2:
0972         return i18n("max");
0973     }
0974     return i18n("Invalid");
0975 }
0976 
0977 QString equalEpsilonParameterNames(int parameterIndex) {
0978     switch (parameterIndex) {
0979     case 0:
0980         return i18n("v1");
0981     case 1:
0982         return i18n("v2");
0983     case 2:
0984         return i18n("ep");
0985     }
0986     return i18n("Invalid");
0987 }