File indexing completed on 2026-08-06 09:24:14
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef HERWIG_RandomHelpers_H
0010 #define HERWIG_RandomHelpers_H
0011
0012 #include "ThePEG/Config/ThePEG.h"
0013
0014 namespace Herwig {
0015
0016 using namespace ThePEG;
0017
0018
0019
0020
0021
0022
0023 namespace RandomHelpers {
0024
0025
0026
0027
0028
0029
0030 inline double sign(double x) {
0031 return x < 0. ? -1. : 1.;
0032 }
0033
0034
0035
0036
0037
0038
0039 template<class Density>
0040 struct Generator {
0041
0042
0043
0044
0045 double lower() const;
0046
0047
0048
0049
0050 double upper() const;
0051
0052
0053
0054
0055 double value(double x) const;
0056
0057
0058
0059
0060 double normalization() const;
0061
0062
0063
0064
0065
0066 double operator()(double r) const;
0067
0068 };
0069
0070
0071
0072
0073
0074
0075 struct Expression {};
0076
0077
0078
0079
0080
0081
0082 template<>
0083 struct Generator<Expression> {
0084
0085
0086
0087
0088 virtual ~Generator() {}
0089
0090
0091
0092
0093 virtual double lower() const = 0;
0094
0095
0096
0097
0098 virtual double upper() const = 0;
0099
0100
0101
0102
0103 virtual double value(double x) const = 0;
0104
0105
0106
0107
0108 virtual double normalization() const = 0;
0109
0110
0111
0112
0113
0114 virtual double operator()(double r) const = 0;
0115
0116 };
0117
0118
0119
0120
0121
0122
0123 template<class Density>
0124 struct Container {};
0125
0126
0127
0128
0129
0130
0131 template<class Density>
0132 class Generator<Container<Density> >
0133 : public Generator<Expression> {
0134
0135
0136
0137
0138 Generator<Density> generator;
0139
0140 public:
0141
0142
0143
0144
0145 Generator(const Generator<Density>& gen)
0146 : generator(gen) {}
0147
0148
0149
0150
0151 virtual double lower() const { return generator.lower(); }
0152
0153
0154
0155
0156 virtual double upper() const { return generator.upper(); }
0157
0158
0159
0160
0161 virtual double value(double x) const { return generator.value(x); }
0162
0163
0164
0165
0166 virtual double normalization() const { return generator.normalization(); }
0167
0168
0169
0170
0171
0172 virtual double operator()(double r) const { return generator(r); }
0173
0174 };
0175
0176
0177
0178
0179
0180
0181 template<class Density>
0182 pair<double,double> generate(const Generator<Density>& gen,
0183 double r) {
0184 double x = gen(r);
0185
0186 if ( gen.value(x) != 0. )
0187 return make_pair(x,gen.normalization()/gen.value(x));
0188 else
0189 return make_pair(x,0.);
0190 }
0191
0192
0193
0194
0195
0196
0197 template<class Density>
0198 struct Remap {};
0199
0200
0201
0202
0203
0204
0205 template<class Density>
0206 class Generator<Remap<Density> > {
0207
0208
0209
0210
0211 Generator<Density> theGenerator;
0212
0213
0214
0215
0216 double theLower;
0217
0218
0219
0220
0221 double theUpper;
0222
0223
0224
0225
0226 Generator(const Generator<Density>& gen,
0227 double low, double up)
0228 : theGenerator(gen), theLower(low), theUpper(up) {
0229 if ( low >= up )
0230 throw std::logic_error("[Generator<Remap>] Invalid boundaries.");
0231 }
0232
0233
0234
0235
0236 const Generator<Density>& generator() const { return theGenerator; }
0237
0238
0239
0240
0241 double lower() const { return theLower; }
0242
0243
0244
0245
0246 double upper() const { return theUpper; }
0247
0248
0249
0250
0251 double value(double y) const {
0252 double xm = generator().lower();
0253 double xp = generator().upper();
0254 double ym = lower();
0255 double yp = upper();
0256 double x = ((xp-xm)/(yp-ym))*y+(yp*xm-ym*xp)/(yp-ym);
0257 return generator().value(x);
0258 }
0259
0260
0261
0262
0263 double normalization() const {
0264 double xm = generator().lower();
0265 double xp = generator().upper();
0266 double ym = lower();
0267 double yp = upper();
0268 return ((yp-ym)/(xp-xm))*generator().normalization();
0269 }
0270
0271
0272
0273
0274
0275 double operator()(double r) const {
0276 double xm = generator().lower();
0277 double xp = generator().upper();
0278 double ym = lower();
0279 double yp = upper();
0280 double x = ((yp-ym)/(xp-xm))*generator()(r)+(xp*ym-xm*yp)/(xp-xm);
0281 return x;
0282 }
0283
0284 };
0285
0286
0287
0288
0289
0290
0291 struct on {
0292
0293
0294
0295
0296 double lower;
0297
0298
0299
0300
0301 double upper;
0302
0303
0304
0305
0306 on(double a, double b)
0307 :lower(a), upper(b) {}
0308 };
0309
0310
0311
0312
0313
0314
0315 template<class Density>
0316 Generator<Remap<Density> > operator*(const Generator<Density>& gen,
0317 const on& interval) {
0318 return Generator<Remap<Density> >(gen,interval.lower,interval.upper);
0319 }
0320
0321
0322
0323
0324
0325
0326
0327 template<class Density>
0328 struct Rescale {};
0329
0330
0331
0332
0333
0334
0335 template<class Density>
0336 class Generator<Rescale<Density> > {
0337
0338
0339
0340
0341 Generator<Density> theGenerator;
0342
0343
0344
0345
0346 double theScale;
0347
0348 public:
0349
0350
0351
0352
0353 Generator(const Generator<Density>& gen,
0354 double sc)
0355 : theGenerator(gen), theScale(sc) {
0356 }
0357
0358
0359
0360
0361 const Generator<Density>& generator() const { return theGenerator; }
0362
0363
0364
0365
0366 double scale() const { return theScale; }
0367
0368
0369
0370
0371 double lower() const { return generator().lower(); }
0372
0373
0374
0375
0376 double upper() const { return generator().upper(); }
0377
0378
0379
0380
0381 double value(double x) const {
0382 return scale()*generator().value(x);
0383 }
0384
0385
0386
0387
0388 double normalization() const {
0389 return scale()*generator().normalization();
0390 }
0391
0392
0393
0394
0395
0396 double operator()(double r) const {
0397 return generator()(r);
0398 }
0399
0400 };
0401
0402
0403
0404
0405
0406
0407 template<class Density>
0408 Generator<Rescale<Density> > operator*(double a, const Generator<Density>& gen) {
0409 return Generator<Rescale<Density> >(gen,a);
0410 }
0411
0412
0413
0414
0415
0416
0417 template<class Density1,
0418 class Density2>
0419 struct Sum {};
0420
0421
0422
0423
0424
0425
0426 template<class Density1,
0427 class Density2>
0428 class Generator<Sum<Density1,Density2> > {
0429
0430
0431
0432
0433 Generator<Density1> theFirstGenerator;
0434
0435
0436
0437
0438 Generator<Density2> theSecondGenerator;
0439
0440
0441
0442
0443 double theLower;
0444
0445
0446
0447
0448 double theUpper;
0449
0450
0451
0452
0453
0454 double theFraction;
0455
0456 public:
0457
0458
0459
0460
0461 Generator(const Generator<Density1>& firstGen,
0462 const Generator<Density2>& secondGen)
0463 : theFirstGenerator(firstGen), theSecondGenerator(secondGen),
0464 theLower(min(firstGen.lower(),secondGen.lower())),
0465 theUpper(max(firstGen.upper(),secondGen.upper())),
0466 theFraction(1.) {
0467 theFraction =
0468 firstGenerator().normalization() / normalization();
0469 }
0470
0471
0472
0473
0474 const Generator<Density1>& firstGenerator() const { return theFirstGenerator; }
0475
0476
0477
0478
0479 const Generator<Density2>& secondGenerator() const { return theSecondGenerator; }
0480
0481
0482
0483
0484 double lower() const { return theLower; }
0485
0486
0487
0488
0489 double upper() const { return theUpper; }
0490
0491
0492
0493
0494
0495 double fraction() const { return theFraction; }
0496
0497
0498
0499
0500 double value(double x) const {
0501 double res = 0.;
0502 if ( firstGenerator().lower() <= x &&
0503 x <= firstGenerator().upper() )
0504 res += firstGenerator().value(x);
0505 if ( secondGenerator().lower() <= x &&
0506 x <= secondGenerator().upper() )
0507 res += secondGenerator().value(x);
0508 return res;
0509 }
0510
0511
0512
0513
0514 double normalization() const {
0515 return
0516 firstGenerator().normalization() + secondGenerator().normalization();
0517 }
0518
0519
0520
0521
0522
0523 double operator()(double r) const {
0524 return
0525 r < fraction() ?
0526 firstGenerator()(r/fraction()) :
0527 secondGenerator()((r-fraction())/(1.-fraction()));
0528 }
0529
0530 };
0531
0532
0533
0534
0535
0536
0537 template<class Density1,
0538 class Density2>
0539 Generator<Sum<Density1,Density2> > operator+(const Generator<Density1>& first,
0540 const Generator<Density2>& second) {
0541 return Generator<Sum<Density1,Density2> >(first,second);
0542 }
0543
0544
0545
0546
0547
0548
0549
0550 template<class Density>
0551 struct matcher {
0552
0553
0554
0555
0556 Generator<Density> generator;
0557
0558
0559
0560
0561 matcher(const Generator<Density>& gen)
0562 : generator(gen) {}
0563
0564 };
0565
0566
0567
0568
0569
0570
0571
0572 template<class Density>
0573 matcher<Density> match(const Generator<Density>& gen) {
0574 return matcher<Density>(gen);
0575 }
0576
0577
0578
0579
0580
0581
0582
0583 template<class Density1,
0584 class Density2>
0585 Generator<Sum<Density1,Rescale<Density2> > > operator+(const Generator<Density1>& first,
0586 const matcher<Density2>& second) {
0587 double matching =
0588 first.value(first.upper())/
0589 second.generator.value(second.generator.lower());
0590 return Generator<Sum<Density1,Rescale<Density2> > >(first,matching*second.generator);
0591 }
0592
0593
0594
0595
0596
0597
0598 template<class Density1,
0599 class Density2>
0600 struct Piecewise {};
0601
0602
0603
0604
0605
0606
0607 struct ToBeDefined {};
0608
0609
0610
0611
0612
0613
0614 template<class Density1,
0615 class Density2>
0616 class Generator<Piecewise<Density1,Density2> > {
0617
0618
0619
0620
0621 Generator<Density1> theFirstGenerator;
0622
0623
0624
0625
0626 Generator<Density2> theSecondGenerator;
0627
0628
0629
0630
0631 double theLower;
0632
0633
0634
0635
0636 double theIntermediate;
0637
0638
0639
0640
0641 double theUpper;
0642
0643
0644
0645
0646
0647 double theFraction;
0648
0649 public:
0650
0651
0652
0653
0654 Generator(const Generator<Density1>& firstGen,
0655 const Generator<Density2>& secondGen)
0656 : theFirstGenerator(firstGen), theSecondGenerator(secondGen),
0657 theLower(firstGen.lower()), theIntermediate(firstGen.upper()), theUpper(secondGen.upper()),
0658 theFraction(1.) {
0659 if ( firstGenerator().upper() != secondGenerator().lower() )
0660 throw std::logic_error("[Generator<Piecewise>] Invalid boundaries.");
0661 theFraction =
0662 firstGenerator().normalization() / normalization();
0663 }
0664
0665
0666
0667
0668 const Generator<Density1>& firstGenerator() const { return theFirstGenerator; }
0669
0670
0671
0672
0673 const Generator<Density2>& secondGenerator() const { return theSecondGenerator; }
0674
0675
0676
0677
0678 double lower() const { return theLower; }
0679
0680
0681
0682
0683 double intermediate() const { return theIntermediate; }
0684
0685
0686
0687
0688 double upper() const { return theUpper; }
0689
0690
0691
0692
0693
0694 double fraction() const { return theFraction; }
0695
0696
0697
0698
0699 double value(double x) const {
0700 return
0701 x < intermediate() ?
0702 firstGenerator().value(x) :
0703 secondGenerator().value(x);
0704 }
0705
0706
0707
0708
0709 double normalization() const {
0710 return
0711 firstGenerator().normalization() + secondGenerator().normalization();
0712 }
0713
0714
0715
0716
0717
0718 double operator()(double r) const {
0719 return
0720 r < fraction() ?
0721 firstGenerator()(r/fraction()) :
0722 secondGenerator()((r-fraction())/(1.-fraction()));
0723 }
0724
0725
0726
0727
0728 template<class Density3>
0729 Generator<Piecewise<Piecewise<Density1,Density2>,Density3> >
0730 operator,(const Generator<Density3>& thirdGenerator) {
0731 return
0732 Generator<Piecewise<Piecewise<Density1,Density2>,Density3> >
0733 (*this,thirdGenerator);
0734 }
0735
0736
0737
0738
0739 template<class Density3>
0740 Generator<Piecewise<Piecewise<Density1,Density2>,Rescale<Density3> > >
0741 operator,(const matcher<Density3>& thirdGenerator) {
0742 double matching =
0743 value(upper())/thirdGenerator.generator.value(upper());
0744 return
0745 Generator<Piecewise<Piecewise<Density1,Density2>,Rescale<Density3> > >
0746 (*this,matching*thirdGenerator.generator);
0747 }
0748
0749 };
0750
0751
0752
0753
0754
0755
0756 template<class Density>
0757 struct Generator<Piecewise<Density,ToBeDefined> > {
0758
0759
0760
0761
0762 Generator<Density> generator;
0763
0764
0765
0766
0767 Generator(const Generator<Density>& gen)
0768 : generator(gen) {}
0769
0770
0771
0772
0773 template<class Density2>
0774 Generator<Piecewise<Density,Density2> >
0775 operator,(const Generator<Density2>& secondGen) {
0776 return
0777 Generator<Piecewise<Density,Density2> >
0778 (generator,secondGen);
0779 }
0780
0781
0782
0783
0784 template<class Density2>
0785 Generator<Piecewise<Density,Rescale<Density2> > >
0786 operator,(const matcher<Density2>& secondGen) {
0787 double matching =
0788 generator.value(generator.upper())/secondGen.generator.value(generator.upper());
0789 return
0790 Generator<Piecewise<Density,Rescale<Density2> > >
0791 (generator,matching*secondGen.generator);
0792 }
0793
0794 };
0795
0796
0797
0798
0799
0800
0801 template<>
0802 struct Generator<Piecewise<ToBeDefined,ToBeDefined> > {
0803
0804
0805
0806
0807 template<class Density>
0808 Generator<Piecewise<Density,ToBeDefined> >
0809 operator,(const Generator<Density>& gen) {
0810 return
0811 Generator<Piecewise<Density,ToBeDefined> >(gen);
0812 }
0813
0814 };
0815
0816
0817
0818
0819
0820
0821 inline Generator<Piecewise<ToBeDefined,ToBeDefined> >
0822 piecewise() {
0823 return Generator<Piecewise<ToBeDefined,ToBeDefined> >();
0824 }
0825
0826
0827
0828
0829
0830
0831
0832
0833 struct Flat {};
0834
0835
0836
0837
0838
0839
0840 template<>
0841 class Generator<Flat> {
0842
0843
0844
0845
0846 double theLower;
0847
0848
0849
0850
0851 double theUpper;
0852
0853 public:
0854
0855
0856
0857
0858 Generator(double low, double up)
0859 : theLower(low), theUpper(up) {}
0860
0861
0862
0863
0864 double lower() const { return theLower; }
0865
0866
0867
0868
0869 double upper() const { return theUpper; }
0870
0871
0872
0873
0874 double value(double x) const {
0875 return x>=lower() && x<=upper() ? 1. : 0.;
0876 }
0877
0878
0879
0880
0881 double normalization() const { return upper()-lower(); }
0882
0883
0884
0885
0886
0887 double operator()(double r) const {
0888 return lower() + r*(upper()-lower());
0889 }
0890
0891 };
0892
0893
0894
0895
0896
0897
0898 inline Generator<Flat> flat(double low, double up) {
0899 return Generator<Flat>(low,up);
0900 }
0901
0902
0903
0904
0905
0906
0907 struct Zero {};
0908
0909
0910
0911
0912
0913
0914 template<>
0915 class Generator<Zero> {
0916
0917
0918
0919
0920 double theLower;
0921
0922
0923
0924
0925 double theUpper;
0926
0927 public:
0928
0929
0930
0931
0932 Generator(double low, double up)
0933 : theLower(low), theUpper(up) {}
0934
0935
0936
0937
0938 double lower() const { return theLower; }
0939
0940
0941
0942
0943 double upper() const { return theUpper; }
0944
0945
0946
0947
0948 double value(double x) const {
0949 return x>=lower() && x<=upper() ? Constants::epsilon : 0.;
0950 }
0951
0952
0953
0954
0955 double normalization() const { return 0.; }
0956
0957
0958
0959
0960
0961 double operator()(double r) const {
0962 return lower() + r*(upper()-lower());
0963 }
0964
0965 };
0966
0967
0968
0969
0970
0971
0972 inline Generator<Zero> zero(double low, double up) {
0973 return Generator<Zero>(low,up);
0974 }
0975
0976
0977
0978
0979
0980
0981 struct Inverse {};
0982
0983
0984
0985
0986
0987
0988 template<>
0989 class Generator<Inverse> {
0990
0991
0992
0993
0994 double thePole;
0995
0996
0997
0998
0999 double theLower;
1000
1001
1002
1003
1004 double theUpper;
1005
1006
1007
1008
1009 double theScale;
1010
1011
1012
1013
1014 double theOffset;
1015
1016 public:
1017
1018
1019
1020
1021 Generator(double z,
1022 double l, double u)
1023 : thePole(z),
1024 theLower(l), theUpper(u),
1025 theScale(z < l ? log((u-z)/(l-z)) : log((z-l)/(z-u))),
1026 theOffset(z < l ? log(l-z) : log(z-u)) {
1027 if ( z >= l && z <= u )
1028 throw std::logic_error("[Generator<Inverse>] Pole inside sampling interval.");
1029 }
1030
1031
1032
1033
1034 double lower() const { return theLower; }
1035
1036
1037
1038
1039 double upper() const { return theUpper; }
1040
1041
1042
1043
1044 double pole() const { return thePole; }
1045
1046
1047
1048
1049 double scale() const { return theScale; }
1050
1051
1052
1053
1054 double offset() const { return theOffset; }
1055
1056
1057
1058
1059 double value(double x) const {
1060 return x>=lower() && x<=upper() ? 1/abs(x-pole()) : 0.;
1061 }
1062
1063
1064
1065
1066 double normalization() const {
1067 return scale();
1068 }
1069
1070
1071
1072
1073
1074 double operator()(double r) const {
1075 return pole() + sign(upper()-pole())*exp(scale()*r+offset());
1076 }
1077
1078 };
1079
1080
1081
1082
1083
1084
1085 inline Generator<Inverse> inverse(double z,
1086 double lower, double upper) {
1087 return Generator<Inverse>(z,lower,upper);
1088 }
1089
1090
1091
1092
1093
1094
1095 struct Power {};
1096
1097
1098
1099
1100
1101
1102 template<>
1103 class Generator<Power> {
1104
1105
1106
1107
1108 double thePole;
1109
1110
1111
1112
1113 double thePower;
1114
1115
1116
1117
1118 double theLower;
1119
1120
1121
1122
1123 double theUpper;
1124
1125
1126
1127
1128 double theScale;
1129
1130
1131
1132
1133 double theOffset;
1134
1135 public:
1136
1137
1138
1139
1140 Generator(double z, double p,
1141 double l, double u)
1142 : thePole(z), thePower(p),
1143 theLower(l), theUpper(u),
1144 theScale(z<=l ? (pow(u-z,1.+p)-pow(l-z,1.+p))/(1.+p) : (pow(z-l,1.+p)-pow(z-u,1.+p))/(1.+p)),
1145 theOffset(z<=l ? pow(l-z,1.+p)/(1.+p) : pow(z-u,1.+p)/(1.+p)) {
1146 if ( p == -1. )
1147 throw std::logic_error("[Generator<Power>] Unit inverse. Consider using inverse().");
1148 if ( z >= l && z <= u && p < 0. )
1149 throw std::logic_error("[Generator<Power>] Pole inside sampling interval.");
1150 if ( z >= l && z <= u && p > 0. )
1151 throw std::logic_error("[Generator<Power>] Zero inside sampling interval.");
1152 }
1153
1154
1155
1156
1157 double lower() const { return theLower; }
1158
1159
1160
1161
1162 double upper() const { return theUpper; }
1163
1164
1165
1166
1167 double pole() const { return thePole; }
1168
1169
1170
1171
1172 double power() const { return thePower; }
1173
1174
1175
1176
1177 double scale() const { return theScale; }
1178
1179
1180
1181
1182 double offset() const { return theOffset; }
1183
1184
1185
1186
1187 double value(double x) const {
1188 return x>=lower() && x<=upper() ? pow(abs(x-pole()),power()) : 0.;
1189 }
1190
1191
1192
1193
1194 double normalization() const {
1195 return scale();
1196 }
1197
1198
1199
1200
1201
1202 double operator()(double r) const {
1203 return pole() + sign(upper()-pole())*pow((1.+power())*(scale()*r+offset()),1./(1.+power()));
1204 }
1205
1206 };
1207
1208
1209
1210
1211
1212
1213 inline Generator<Power> power(double z, double p,
1214 double lower, double upper) {
1215 return Generator<Power>(z,p,lower,upper);
1216 }
1217
1218
1219
1220
1221
1222
1223 struct BreitWigner {};
1224
1225
1226
1227
1228
1229
1230 template<>
1231 class Generator<BreitWigner> {
1232
1233
1234
1235
1236 double thePole;
1237
1238
1239
1240
1241 double theWidth;
1242
1243
1244
1245
1246 double theLower;
1247
1248
1249
1250
1251 double theUpper;
1252
1253
1254
1255
1256 double theScale;
1257
1258
1259
1260
1261 double theOffset;
1262
1263
1264
1265
1266 double theSqrtWidth;
1267
1268 public:
1269
1270
1271
1272
1273 Generator(double z, double w,
1274 double l, double u)
1275 : thePole(z), theWidth(w),
1276 theLower(l), theUpper(u),
1277 theScale((atan((u-z)/sqrt(abs(w*z)))-atan((l-z)/sqrt(abs(w*z))))/sqrt(abs(w*z))),
1278 theOffset(atan((l-z)/sqrt(abs(w*z)))/sqrt(abs(w*z))),
1279 theSqrtWidth(sqrt(abs(w*z))) {
1280 if ( w == 0. )
1281 throw std::logic_error("[Generator<BreitWigner>] Zero width. Consider using power().");
1282 }
1283
1284
1285
1286
1287 double lower() const { return theLower; }
1288
1289
1290
1291
1292 double upper() const { return theUpper; }
1293
1294
1295
1296
1297 double pole() const { return thePole; }
1298
1299
1300
1301
1302 double width() const { return theWidth; }
1303
1304
1305
1306
1307 double scale() const { return theScale; }
1308
1309
1310
1311
1312 double offset() const { return theOffset; }
1313
1314
1315
1316
1317 double sqrtWidth() const { return theSqrtWidth; }
1318
1319
1320
1321
1322 double value(double x) const {
1323 return
1324 x>=lower() && x<=upper() ?
1325 1./(sqr(x-pole())+abs(width()*pole())) : 0.;
1326 }
1327
1328
1329
1330
1331 double normalization() const {
1332 return scale();
1333 }
1334
1335
1336
1337
1338
1339 double operator()(double r) const {
1340 double res = pole() + sqrtWidth()*tan(sqrtWidth()*(scale()*r+offset()));
1341 if ( res <= lower() ) return lower()*(1+std::numeric_limits<double>::epsilon());
1342 else if ( res >= upper() ) return upper()*(1-std::numeric_limits<double>::epsilon());
1343 else return res;
1344 }
1345
1346 };
1347
1348
1349
1350
1351
1352
1353 inline Generator<BreitWigner> breitWigner(double z, double w,
1354 double lower, double upper) {
1355 return Generator<BreitWigner>(z,w,lower,upper);
1356 }
1357
1358 }
1359
1360 }
1361
1362 #endif