ComPWA
Common Partial-Wave-Analysis Framework
Functions.cpp
Go to the documentation of this file.
1 // Copyright (c) 2013, 2017 The ComPWA Team.
2 // This file is part of the ComPWA framework, check
3 // https://github.com/ComPWA/ComPWA/license.txt for details.
4 
5 #include <cmath>
6 #include <functional>
7 #include <numeric>
8 
9 #include "Functions.hpp"
10 
11 #include "ThirdParty/parallelstl/include/pstl/algorithm"
12 #include "ThirdParty/parallelstl/include/pstl/execution"
13 
14 namespace ComPWA {
15 namespace FunctionTree {
16 
17 void Inverse::execute(ParameterList &paras, std::shared_ptr<Parameter> &out) {
18  if (out && checkType != out->type())
19  throw BadParameter("Inverse::execute() | Parameter type mismatch!");
20 
21  if ((paras.doubleValues().size() + paras.doubleParameters().size()) != 1)
22  throw BadParameter(
23  "Inverse::execute() | Expecting a single parameter or value in list");
24 
25  switch (checkType) {
26  case ParType::DOUBLE: {
27  // Create parameter if not there
28  if (!out)
29  out = std::make_shared<Value<double>>();
30  auto par = std::static_pointer_cast<Value<double>>(out);
31  auto &result = par->operator()();
32  double var;
33  if (paras.doubleValues().size() == 1) {
34  var = paras.doubleValue(0)->value();
35  } else if (paras.doubleParameters().size() == 1) {
36  var = paras.doubleParameter(0)->value();
37  } else {
38  throw BadParameter(
39  "Inverse::execute() | Expecting a single parameter or value in list");
40  }
41  if (var == 0) {
42  result = 0;
43  LOG(ERROR) << "Inverse::execute() | Division by zero";
44  } else
45  result = 1 / var;
46  break;
47  }
48  default: {
49  throw BadParameter("Inverse::execute() | Parameter of type " +
50  std::to_string(checkType) + " can not be handled");
51  }
52  }
53 }
54 
56  std::shared_ptr<Parameter> &out) {
57  if (out && checkType != out->type())
58  throw BadParameter("Inverse::SquareRoot() | Parameter type mismatch!");
59 
60  if ((paras.doubleValues().size() + paras.doubleParameters().size()) != 1)
61  throw BadParameter(
62  "SquareRoot::execute() | Expecting a single parameter in list");
63 
64  switch (checkType) {
65  case ParType::DOUBLE: {
66  // Create parameter if not there
67  if (!out)
68  out = std::make_shared<Value<double>>();
69  auto par = std::static_pointer_cast<Value<double>>(out);
70  auto &result = par->operator()();
71  double var = 0;
72  if (paras.doubleValues().size() == 1) {
73  var = paras.doubleValue(0)->value();
74  } else if (paras.doubleParameters().size() == 1) {
75  var = paras.doubleParameter(0)->value();
76  } else {
77  throw BadParameter("SquareRoot::execute() | Expecting a single parameter "
78  "or value in list");
79  }
80  result = std::sqrt(var);
81  break;
82  }
83  default: {
84  throw BadParameter("SquareRoot::execute() | Parameter of type " +
85  std::to_string(checkType) + " can not be handled");
86  }
87  } // end switch
88 }
89 
91  double sum;
92  double correction;
93 };
94 
98 KahanSummation KahanSum(KahanSummation accumulation, double value) {
99  KahanSummation result;
100  double y = value - accumulation.correction;
101  double t = accumulation.sum + y;
102  result.correction = (t - accumulation.sum) - y;
103  result.sum = t;
104  return result;
105 }
106 
107 void AddAll::execute(ParameterList &paras, std::shared_ptr<Parameter> &out) {
108  if (out && checkType != out->type())
109  throw BadParameter("AddAll::SquareRoot() | Parameter type mismatch!");
110 
111  switch (checkType) {
112  // For multi values we perform a vector addition. All multi values are added
113  // and casted to the respective return
114  case ParType::MCOMPLEX: {
115  size_t n;
116  if (paras.mComplexValues().size())
117  n = paras.mComplexValue(0)->values().size();
118  else if (paras.mDoubleValues().size())
119  n = paras.mDoubleValue(0)->values().size();
120  else if (paras.mDoubleValues().size())
121  n = paras.mIntValue(0)->values().size();
122  else
123  throw BadParameter(
124  "AddAll::execute() | Expecting at least one multi value.");
125 
126  if (!out)
127  out = MComplex("", n);
128 
129  // fill MultiComplex parameter
130  auto par =
131  std::static_pointer_cast<Value<std::vector<std::complex<double>>>>(out);
132  auto &results = par->values(); // reference
133  if (results.size() != n) {
134  results.resize(n);
135  }
136  // first get all the scalar inputs and add them
137  double initial_real(0.0);
138  for (auto const x : paras.doubleValues())
139  initial_real += x->value();
140  std::complex<double> initial_value(initial_real, 0.0);
141  for (auto const x : paras.complexValues())
142  initial_value += x->value();
143  std::fill(pstl::execution::par_unseq, results.begin(), results.end(),
144  initial_value); // reset
145 
146  for (auto dv : paras.mComplexValues()) {
147  if (dv->values().size() != n)
148  throw BadParameter(
149  "AddAll::execute() | MCOMPLEX: Size of multi complex "
150  "value does not match!");
151  std::transform(pstl::execution::par_unseq, results.begin(), results.end(),
152  dv->values().begin(), results.begin(),
153  std::plus<std::complex<double>>());
154  }
155  for (auto dv : paras.mDoubleValues()) {
156  if (dv->values().size() != n)
157  throw BadParameter("AddAll::execute() | MCOMPLEX: Size of multi double "
158  "value does not match!");
159  std::transform(pstl::execution::par_unseq, results.begin(), results.end(),
160  dv->values().begin(), results.begin(),
161  std::plus<std::complex<double>>());
162  }
163  for (auto dv : paras.mIntValues()) {
164  if (dv->values().size() != n)
165  throw BadParameter("AddAll::execute() | MCOMPLEX: Size of multi int "
166  "value does not match!");
167  std::transform(pstl::execution::par_unseq, results.begin(), results.end(),
168  dv->values().begin(), results.begin(),
169  std::plus<std::complex<double>>());
170  }
171  break;
172  } // end multi complex
173  case ParType::MDOUBLE: {
174  size_t n;
175  if (paras.mComplexValues().size())
176  throw BadParameter("AddAll::execute() | Return type is double but "
177  "complex value was found!");
178  else if (paras.mDoubleValues().size())
179  n = paras.mDoubleValue(0)->values().size();
180  else if (paras.mDoubleValues().size())
181  n = paras.mIntValue(0)->values().size();
182  else
183  throw BadParameter(
184  "AddAll::execute() | Expecting at least one multi value.");
185  // Create parameter if not there
186  if (!out)
187  out = MDouble("", n);
188  auto par = std::static_pointer_cast<Value<std::vector<double>>>(out);
189  auto &results = par->values(); // reference
190  if (results.size() != n) {
191  results.resize(n);
192  }
193  // first get all the scalar inputs and add them
194  double initial_value(0.0);
195  for (auto const x : paras.doubleValues())
196  initial_value += x->value();
197  std::fill(pstl::execution::par_unseq, results.begin(), results.end(),
198  initial_value); // reset
199 
200  for (auto dv : paras.mDoubleValues()) {
201  if (dv->values().size() != results.size())
202  throw BadParameter("AddAll::execute() | MDOUBLE: Size of multi double "
203  "value does not match!");
204  std::transform(pstl::execution::par_unseq, results.begin(), results.end(),
205  dv->values().begin(), results.begin(),
206  std::plus<double>());
207  }
208  for (auto dv : paras.mIntValues()) {
209  if (dv->values().size() != results.size())
210  throw BadParameter("AddAll::execute() | MDOUBLE: Size of multi double "
211  "value does not match!");
212  std::transform(pstl::execution::par_unseq, results.begin(), results.end(),
213  dv->values().begin(), results.begin(),
214  std::plus<double>());
215  }
216  break;
217  } // end multi double
218  case ParType::MINTEGER: {
219  size_t n;
220  if (paras.mComplexValues().size())
221  throw BadParameter("AddAll::execute() | Return type is double but "
222  "complex value was found!");
223  else if (paras.mDoubleValues().size())
224  throw BadParameter("AddAll::execute() | Return type is int but "
225  "double value was found!");
226  else if (paras.mDoubleValues().size())
227  n = paras.mIntValue(0)->values().size();
228  else
229  throw BadParameter(
230  "AddAll::execute() | Expecting at least one multi value.");
231  // Create parameter if not there
232  if (!out)
233  out = MInteger("", n);
234 
235  auto par = std::static_pointer_cast<Value<std::vector<int>>>(out);
236  auto &results = par->values(); // reference
237  if (results.size() != n) {
238  results.resize(n);
239  }
240  std::fill(pstl::execution::par_unseq, results.begin(), results.end(),
241  0); // reset
242 
243  // fill multi integer parameter
244  for (auto dv : paras.mIntValues()) {
245  if (dv->values().size() != results.size())
246  throw BadParameter("AddAll::execute() | MDOUBLE: Size of multi double "
247  "value does not match!");
248  std::transform(pstl::execution::par_unseq, results.begin(), results.end(),
249  dv->values().begin(), results.begin(), std::plus<int>());
250  }
251  break;
252  } // end multi double
253 
254  case ParType::COMPLEX: {
255  if (!(paras.complexValues().size() || paras.doubleValues().size() ||
256  paras.intValues().size()))
257  throw BadParameter("AddAll::execute() | COMPLEX: expecting at least "
258  "one single value!");
259  // Create parameter if not there
260  if (!out)
261  out = std::make_shared<Value<std::complex<double>>>();
262  auto par = std::static_pointer_cast<Value<std::complex<double>>>(out);
263  auto &result = par->values(); // reference
264  result = std::complex<double>(0, 0); // reset
265 
266  for (auto dv : paras.complexValues())
267  result += dv->value();
268  for (auto dv : paras.doubleValues())
269  result += dv->value();
270  for (auto dv : paras.doubleParameters())
271  result += dv->value();
272  for (auto dv : paras.intValues())
273  result += dv->value();
274 
275  // collapse multi values
276  for (auto dv : paras.mComplexValues())
277  result +=
278  std::accumulate(dv->values().begin(), dv->values().end(), result);
279 
280  for (auto dv : paras.mDoubleValues())
281  result +=
282  std::accumulate(dv->values().begin(), dv->values().end(), result);
283 
284  for (auto dv : paras.mIntValues())
285  result += std::accumulate(dv->values().begin(), dv->values().end(), 0);
286 
287  break;
288  } // end complex
289 
290  case ParType::DOUBLE: {
291  // Create parameter if not there
292  if (!out)
293  out = std::make_shared<Value<double>>();
294  auto par = std::static_pointer_cast<Value<double>>(out);
295  auto &result = par->values(); // reference
296  result = 0.; // reset
297 
298  for (auto dv : paras.doubleValues())
299  result += dv->value();
300  for (auto dv : paras.doubleParameters())
301  result += dv->value();
302  for (auto dv : paras.intValues())
303  result += dv->value();
304 
305  // collapse multi values
306  for (auto dv : paras.mDoubleValues()) {
307  KahanSummation kaSum = {result};
308  auto kaResult = std::accumulate(dv->values().begin(), dv->values().end(),
309  kaSum, KahanSum);
310  result += kaResult.sum;
311  }
312  for (auto dv : paras.mIntValues()) {
313  KahanSummation kaSum = {result};
314  auto kaResult = std::accumulate(dv->values().begin(), dv->values().end(),
315  kaSum, KahanSum);
316  result += kaResult.sum;
317  }
318  break;
319  } // end double
320 
321  case ParType::INTEGER: {
322  // Create parameter if not there
323  if (!out)
324  out = std::make_shared<Value<int>>();
325  auto par = std::static_pointer_cast<Value<int>>(out);
326  auto &result = par->values(); // reference
327  result = 0; // reset
328  for (auto dv : paras.intValues())
329  result += dv->value();
330 
331  // collapse multi values
332  for (auto dv : paras.mIntValues()) {
333  KahanSummation kaSum = {(double)result};
334  auto kaResult = std::accumulate(dv->values().begin(), dv->values().end(),
335  kaSum, KahanSum);
336  result += kaResult.sum;
337  }
338  break;
339  } // end int
340  default: {
341  throw BadParameter("AddAll::execute() | Parameter of type " +
342  std::to_string(checkType) + " can not be handled");
343  }
344  } // end switch
345 }
346 
347 void MultAll::execute(ParameterList &paras, std::shared_ptr<Parameter> &out) {
348  if (out && checkType != out->type())
349  throw BadParameter("MultAll::execute() | Parameter type mismatch!");
350 
351  size_t nMC = paras.mComplexValues().size();
352  size_t nMD = paras.mDoubleValues().size();
353  size_t nMI = paras.mIntValues().size();
354  size_t nC = paras.complexValues().size();
355  size_t nD = paras.doubleValues().size() + paras.doubleParameters().size();
356  size_t nI = paras.intValues().size();
357 
358  switch (checkType) {
359 
360  case ParType::MCOMPLEX: {
361  // output multi complex: treat everything non-complex as real,
362  // there must be multi complex input
363  if (!(nMC > 0 || (nMD > 0 && nC > 0)))
364  throw BadParameter(
365  "MultAll::execute() | MCOMPLEX: expecting at least "
366  "one multi complex value or a multi double and a complex scalar!");
367 
368  std::complex<double> result(1., 0.); // mult up all 1-dim input
369  for (auto p : paras.complexValues())
370  result *= p->value();
371  for (auto p : paras.doubleValues())
372  result *= p->value();
373  for (auto p : paras.doubleParameters())
374  result *= p->value();
375  for (auto p : paras.intValues())
376  result *= p->value();
377 
378  size_t n(0);
379  if (nMC > 0)
380  n = paras.mComplexValue(0)->values().size();
381  if (n == 0 && nMC == 0) {
382  // if there is no multi complex as input but a scalar complex which
383  // should be multiplied on a multi double
384  n = paras.mDoubleValue(0)->values().size();
385  }
386  if (!out)
387  out = MComplex("", n);
388  auto par =
389  std::static_pointer_cast<Value<std::vector<std::complex<double>>>>(out);
390  auto &results = par->values(); // reference
391  if (results.size() != n) {
392  results.resize(n);
393  }
394  std::fill(pstl::execution::par_unseq, results.begin(), results.end(),
395  result); // reset
396 
397  for (auto p : paras.mComplexValues()) {
398  std::transform(pstl::execution::par_unseq, p->values().begin(),
399  p->values().end(), results.begin(), results.begin(),
400  std::multiplies<std::complex<double>>());
401  }
402  for (auto p : paras.mDoubleValues()) {
403  std::transform(pstl::execution::par_unseq, p->values().begin(),
404  p->values().end(), results.begin(), results.begin(),
405  std::multiplies<std::complex<double>>());
406  }
407  for (auto p : paras.mIntValues()) {
408  std::transform(pstl::execution::par_unseq, p->values().begin(),
409  p->values().end(), results.begin(), results.begin(),
410  std::multiplies<std::complex<double>>());
411  }
412  break;
413  } // end multi complex
414  case ParType::MDOUBLE: {
415  // output multi double: ignore complex pars, there must be
416  // multi double input
417  if (!nMD || nMC)
418  throw BadParameter(
419  "MultAll::execute() | MDOUBLE: Number and/or types do not match");
420 
421  double result = 1.;
422  for (auto p : paras.doubleValues())
423  result *= p->value();
424  for (auto p : paras.doubleParameters())
425  result *= p->value();
426  for (auto p : paras.intValues())
427  result *= p->value();
428 
429  size_t n = paras.mDoubleValue(0)->values().size();
430  if (!out)
431  out = MDouble("", n);
432  // fill MultiComplex parameter
433  auto par = std::static_pointer_cast<Value<std::vector<double>>>(out);
434  auto &results = par->values(); // reference
435  if (results.size() != n) {
436  results.resize(n);
437  }
438  std::fill(pstl::execution::par_unseq, results.begin(), results.end(),
439  result); // reset
440 
441  for (auto p : paras.mDoubleValues()) {
442  std::transform(pstl::execution::par_unseq, p->values().begin(),
443  p->values().end(), results.begin(), results.begin(),
444  std::multiplies<double>());
445  }
446  for (auto p : paras.mIntValues()) {
447  std::transform(pstl::execution::par_unseq, p->values().begin(),
448  p->values().end(), results.begin(), results.begin(),
449  std::multiplies<double>());
450  }
451  break;
452  } // end multi double
453 
454  case ParType::MINTEGER: {
455  // output multi double: ignore complex pars, there must be
456  // multi double input
457  if (!nMI || nMC || nMD)
458  throw BadParameter(
459  "MultAll::execute() | MDOUBLE: Number and/or types do not match");
460 
461  int result = 1.;
462  for (auto p : paras.intValues())
463  result *= p->value();
464 
465  size_t n = paras.mIntValue(0)->values().size();
466  if (!out)
467  out = MInteger("", n);
468 
469  // fill MultiComplex parameter
470  auto par = std::static_pointer_cast<Value<std::vector<int>>>(out);
471  auto &results = par->values(); // reference
472  if (results.size() != n) {
473  results.resize(n);
474  }
475  std::fill(pstl::execution::par_unseq, results.begin(), results.end(),
476  result); // reset
477 
478  for (auto p : paras.mIntValues()) {
479  std::transform(pstl::execution::par_unseq, p->values().begin(),
480  p->values().end(), results.begin(), results.begin(),
481  std::multiplies<int>());
482  }
483  break;
484  } // end multi int
485 
486  case ParType::COMPLEX: {
487  // output complex: collapse everything non-complex as real-part
488 
489  if (!nC || nMD || nMC || nMI)
490  throw BadParameter("MultAll::execute() | COMPLEX: expecting at least "
491  "one multi complex value!");
492  if (!out)
493  out = std::make_shared<Value<std::complex<double>>>();
494  auto par = std::static_pointer_cast<Value<std::complex<double>>>(out);
495  auto &result = par->values(); // reference
496  result = std::complex<double>(1., 0.); // reset
497 
498  for (auto p : paras.complexValues())
499  result *= p->value();
500  for (auto p : paras.doubleValues())
501  result *= p->value();
502  for (auto p : paras.doubleParameters())
503  result *= p->value();
504  for (auto p : paras.intValues())
505  result *= p->value();
506  break;
507  } // end complex
508 
509  case ParType::DOUBLE: {
510  if (!nD || nC || nMD || nMC || nMI)
511  throw BadParameter("MultAll::execute() | DOUBLE: expecting at least "
512  "one multi complex value!");
513  if (!out)
514  out = std::make_shared<Value<double>>();
515  auto par = std::static_pointer_cast<Value<double>>(out);
516  auto &result = par->values(); // reference
517  result = 1.; // reset
518 
519  for (auto p : paras.doubleValues())
520  result *= p->value();
521  for (auto p : paras.doubleParameters())
522  result *= p->value();
523  for (auto p : paras.intValues())
524  result *= p->value();
525  break;
526  } // end double
527  case ParType::INTEGER: {
528  if (!nI || nD || nC || nMD || nMC || nMI)
529  throw BadParameter("MultAll::execute() | INTEGER: expecting at least "
530  "one multi complex value!");
531  if (!out)
532  out = std::make_shared<Value<int>>();
533  auto par = std::static_pointer_cast<Value<int>>(out);
534  auto &result = par->values(); // reference
535  result = 1; // reset
536 
537  for (auto p : paras.intValues())
538  result *= p->value();
539  break;
540  } // end double
541  default: {
542  throw BadParameter("MultAll::execute() | Parameter of type " +
543  std::to_string(checkType) + " can not be handled");
544  }
545  } // end switch
546 }
547 
548 void LogOf::execute(ParameterList &paras, std::shared_ptr<Parameter> &out) {
549  if (out && checkType != out->type())
550  throw BadParameter("LogOf::execute() | Parameter type mismatch!");
551 
552  if (paras.numParameters() + paras.numValues() != 1)
553  throw BadParameter("LogOf::execute() | Expecting only one parameter");
554 
555  // size_t nMC = paras.mComplexValues().size();
556  size_t nMD = paras.mDoubleValues().size();
557  size_t nMI = paras.mIntValues().size();
558  // size_t nC = paras.complexValues().size();
559  size_t nD = paras.doubleValues().size() + paras.doubleParameters().size();
560  size_t nI = paras.intValues().size();
561 
562  switch (checkType) {
563  case ParType::MDOUBLE: {
564  // output multi double: input must be one multi double
565  if (!nMD && !nMI)
566  throw BadParameter(
567  "LogOf::execute() | MDOUBLE: Number and/or types do not match");
568 
569  if (nMD) {
570  size_t n = paras.mDoubleValue(0)->values().size();
571  if (!out)
572  out = MDouble("", n);
573  auto par = std::static_pointer_cast<Value<std::vector<double>>>(out);
574  auto &results = par->values(); // reference
575  if (results.size() != n) {
576  results.resize(n);
577  }
578  std::fill(pstl::execution::par_unseq, results.begin(), results.end(),
579  0.); // reset
580  std::transform(pstl::execution::par_unseq,
581  paras.mDoubleValue(0)->operator()().begin(),
582  paras.mDoubleValue(0)->operator()().end(), results.begin(),
583  [](double x) { return std::log(x); });
584  }
585  if (nMI) {
586  size_t n = paras.mIntValue(0)->values().size();
587  if (!out)
588  out = MDouble("", n);
589  auto par = std::static_pointer_cast<Value<std::vector<double>>>(out);
590  auto &results = par->values(); // reference
591  if (results.size() != n) {
592  results.resize(n);
593  }
594  std::transform(pstl::execution::par_unseq,
595  paras.mIntValue(0)->operator()().begin(),
596  paras.mIntValue(0)->operator()().end(), results.begin(),
597  [](double x) { return std::log(x); });
598  }
599  break;
600  } // end multi double
601 
602  case ParType::DOUBLE: {
603  if (!nD && !nI)
604  throw BadParameter(
605  "LogOf::execute() | DOUBLE: Number and/or types do not match");
606 
607  if (!out)
608  out = std::make_shared<Value<double>>();
609  auto par = std::static_pointer_cast<Value<double>>(out);
610  auto &result = par->values(); // reference
611 
612  // output double: log of one double input
613  if (paras.doubleValues().size())
614  result = std::log(paras.doubleValue(0)->value());
615  else if (paras.doubleParameters().size())
616  result = std::log(paras.doubleParameter(0)->value());
617  else if (paras.intValues().size())
618  result = std::log(paras.intValue(0)->value());
619  else
620  throw std::runtime_error("LogOf::execute() | DOUBLE: something is wrong. "
621  "We should not arrive here!");
622  break;
623  } // end double
624  default: {
625  throw BadParameter("LogOf::execute() | Parameter of type " +
626  std::to_string(checkType) + " can not be handled");
627  }
628  } // end switch
629 };
630 
631 void Exp::execute(ParameterList &paras, std::shared_ptr<Parameter> &out) {
632  if (out && checkType != out->type())
633  throw BadParameter("Exp::execute() | Parameter type mismatch!");
634 
635  if (paras.numParameters() + paras.numValues() != 1)
636  throw BadParameter("Exp::execute() | Expecting only one parameter");
637 
638  // size_t nMC = paras.mComplexValues().size();
639  size_t nMD = paras.mDoubleValues().size();
640  size_t nMI = paras.mIntValues().size();
641  // size_t nC = paras.complexValues().size();
642  size_t nD = paras.doubleValues().size() + paras.doubleParameters().size();
643  size_t nI = paras.intValues().size();
644 
645  switch (checkType) {
646  case ParType::MDOUBLE: {
647  // output multi double: input must be one multi double
648  if (!nMD && !nMI)
649  throw BadParameter(
650  "Exp::execute() | MDOUBLE: Number and/or types do not match");
651 
652  if (nMD) {
653  size_t n = paras.mDoubleValue(0)->values().size();
654  if (!out)
655  out = MDouble("", n);
656  auto par = std::static_pointer_cast<Value<std::vector<double>>>(out);
657  auto &results = par->values(); // reference
658  if (results.size() != n) {
659  results.resize(n);
660  }
661  std::fill(pstl::execution::par_unseq, results.begin(), results.end(),
662  0.); // reset
663  std::transform(pstl::execution::par_unseq,
664  paras.mDoubleValue(0)->operator()().begin(),
665  paras.mDoubleValue(0)->operator()().end(), results.begin(),
666  [](double x) { return std::exp(x); });
667  }
668  if (nMI) {
669  size_t n = paras.mIntValue(0)->values().size();
670  if (!out)
671  out = MDouble("", n);
672  auto par = std::static_pointer_cast<Value<std::vector<double>>>(out);
673  auto &results = par->values(); // reference
674  if (results.size() != n) {
675  results.resize(n);
676  }
677  std::transform(pstl::execution::par_unseq,
678  paras.mIntValue(0)->operator()().begin(),
679  paras.mIntValue(0)->operator()().end(), results.begin(),
680  [](double x) { return std::exp(x); });
681  }
682  break;
683  } // end multi double
684 
685  case ParType::DOUBLE: {
686  if (!nD && !nI)
687  throw BadParameter(
688  "Exp::execute() | DOUBLE: Number and/or types do not match");
689 
690  if (!out)
691  out = std::make_shared<Value<double>>();
692  auto par = std::static_pointer_cast<Value<double>>(out);
693  auto &result = par->values(); // reference
694 
695  // output double: log of one double input
696  if (paras.doubleValues().size())
697  result = std::exp(paras.doubleValue(0)->value());
698  else if (paras.doubleParameters().size())
699  result = std::exp(paras.doubleParameter(0)->value());
700  else if (paras.intValues().size())
701  result = std::log(paras.intValue(0)->value());
702  else
703  throw std::runtime_error("Exp::execute() | DOUBLE: something is wrong. "
704  "We should not arrive here!");
705  break;
706  } // end double
707  default: {
708  throw BadParameter("Exp::execute() | Parameter of type " +
709  std::to_string(checkType) + " can not be handled");
710  }
711  } // end switch
712 };
713 
714 void Pow::execute(ParameterList &paras, std::shared_ptr<Parameter> &out) {
715  if (out && checkType != out->type())
716  throw BadParameter("Pow::execute() | Parameter type mismatch!");
717 
718  if (paras.numParameters() + paras.numValues() != 1)
719  throw BadParameter("Pow::execute() | Expecting only one parameter");
720 
721  // size_t nMC = paras.mComplexValues().size();
722  size_t nMD = paras.mDoubleValues().size();
723  size_t nMI = paras.mIntValues().size();
724  // size_t nC = paras.complexValues().size();
725  size_t nD = paras.doubleValues().size() + paras.doubleParameters().size();
726  size_t nI = paras.intValues().size();
727 
728  int powerCopy(power);
729  switch (checkType) {
730  case ParType::MDOUBLE: {
731  // output multi double: input must be one multi double
732  if (!nMD && !nMI)
733  throw BadParameter(
734  "Pow::execute() | MDOUBLE: Number and/or types do not match");
735 
736  if (nMD) {
737  size_t n = paras.mDoubleValue(0)->values().size();
738  if (!out)
739  out = MDouble("", n);
740  auto par = std::static_pointer_cast<Value<std::vector<double>>>(out);
741  auto &results = par->values(); // reference
742  if (results.size() != n) {
743  results.resize(n);
744  }
745  std::fill(pstl::execution::par_unseq, results.begin(), results.end(),
746  0.); // reset
747  std::transform(pstl::execution::par_unseq,
748  paras.mDoubleValue(0)->operator()().begin(),
749  paras.mDoubleValue(0)->operator()().end(), results.begin(),
750  [powerCopy](double x) { return std::pow(x, powerCopy); });
751  }
752  if (nMI) {
753  size_t n = paras.mIntValue(0)->values().size();
754  if (!out)
755  out = MDouble("", n);
756  auto par = std::static_pointer_cast<Value<std::vector<double>>>(out);
757  auto &results = par->values(); // reference
758  if (results.size() != n) {
759  results.resize(n);
760  }
761  std::transform(pstl::execution::par_unseq,
762  paras.mIntValue(0)->operator()().begin(),
763  paras.mIntValue(0)->operator()().end(), results.begin(),
764  [powerCopy](double x) { return std::pow(x, powerCopy); });
765  }
766  break;
767  } // end multi double
768 
769  case ParType::DOUBLE: {
770  if (!nD && !nI)
771  throw BadParameter(
772  "Pow::execute() | DOUBLE: Number and/or types do not match");
773 
774  if (!out)
775  out = std::make_shared<Value<double>>();
776  auto par = std::static_pointer_cast<Value<double>>(out);
777  auto &result = par->values(); // reference
778 
779  // output double: log of one double input
780  if (paras.doubleValues().size())
781  result = std::pow(paras.doubleValue(0)->value(), power);
782  else if (paras.doubleParameters().size())
783  result = std::pow(paras.doubleParameter(0)->value(), power);
784  else if (paras.intValues().size())
785  result = std::log(paras.intValue(0)->value());
786  else
787  throw std::runtime_error("Pow::execute() | DOUBLE: something is wrong. "
788  "We should not arrive here!");
789  break;
790  } // end double
791  default: {
792  throw BadParameter("Pow::execute() | Parameter of type " +
793  std::to_string(checkType) + " can not be handled");
794  }
795  } // end switch
796 };
797 
799  std::shared_ptr<Parameter> &out) {
800  if (out && checkType != out->type())
801  throw BadParameter("Complexify::SquareRoot() | Parameter type mismatch!");
802 
803  size_t nMC = paras.mComplexValues().size();
804  size_t nMD = paras.mDoubleValues().size();
805  size_t nMI = paras.mIntValues().size();
806  size_t nC = paras.complexValues().size();
807  size_t nD = paras.doubleValues().size() + paras.doubleParameters().size();
808  size_t nI = paras.intValues().size();
809 
810  switch (checkType) {
811  case ParType::MCOMPLEX: {
812  // output multi complex: input must be two multi double
813  if (nMD != 2 || nMC || nMI || nC || nD || nI)
814  throw BadParameter("Complexify::execute() | MCOMPLEX: Number and/or "
815  "types do not match");
816  size_t n = paras.mDoubleValue(0)->values().size();
817  if (!out)
818  out = MComplex("", n);
819  auto par =
820  std::static_pointer_cast<Value<std::vector<std::complex<double>>>>(out);
821  auto &results = par->values(); // reference
822  if (results.size() != n) {
823  results.resize(n);
824  }
825 
826  // We have to assume here that the magnitude is the first parameter and
827  // the phase the second one. We cannot check that.
828  std::transform(
829  pstl::execution::par_unseq, paras.mDoubleValue(0)->operator()().begin(),
830  paras.mDoubleValue(0)->operator()().end(),
831  paras.mDoubleValue(1)->operator()().begin(), results.begin(),
832  [](double r, double phi) { return std::polar(std::abs(r), phi); });
833  break;
834  } // end multi complex
835  case ParType::COMPLEX: {
836  // output complex: input must be two double
837  // output multi complex: input must be two multi double
838  if (nD != 2 || nMC || nMD || nMI || nC || nI)
839  throw BadParameter("Complexify::execute() | COMPLEX: Number and/or "
840  "types do not match");
841  if (!out)
842  out = std::make_shared<Value<std::complex<double>>>();
843  auto par = std::static_pointer_cast<Value<std::complex<double>>>(out);
844  auto &result = par->values(); // reference
845 
846  if (paras.doubleValues().size() == 2) {
847  result = std::polar(std::abs(paras.doubleValue(0)->value()),
848  paras.doubleValue(1)->value());
849  } else if (paras.doubleParameters().size() == 2) {
850  result = std::polar(std::abs(paras.doubleParameter(0)->value()),
851  paras.doubleParameter(1)->value());
852  } else {
853  throw std::runtime_error("LogOf::execute() | DOUBLE: something is wrong. "
854  "We should not arrive here!");
855  }
856  break;
857  } // end double
858  default: {
859  throw BadParameter("Complexify::execute() | Parameter of type " +
860  std::to_string(checkType) + " can not be handled");
861  }
862  } // end switch
863 };
864 
866  std::shared_ptr<Parameter> &out) {
867  if (out && checkType != out->type())
868  throw BadParameter(
869  "ComplexConjugate::SquareRoot() | Parameter type mismatch!");
870 
871  size_t nMC = paras.mComplexValues().size();
872  size_t nMD = paras.mDoubleValues().size();
873  size_t nMI = paras.mIntValues().size();
874  size_t nC = paras.complexValues().size();
875  size_t nD = paras.doubleValues().size() + paras.doubleParameters().size();
876  size_t nI = paras.intValues().size();
877 
878  if (nMD || nMI || nD || nI)
879  throw BadParameter("ComplexConjugate::execute() | Real numbers given. This "
880  "is mathematically correct but not necessary and "
881  "therefore not implemented.");
882 
883  switch (checkType) {
884  case ParType::MCOMPLEX: {
885  // output complex: input must be one multicomplex
886  if (nMC != 1 || nC)
887  throw BadParameter("ComplexConjugate::execute() | MCOMPLEX: Number "
888  "and/or types do not match");
889  size_t n = paras.mComplexValue(0)->values().size();
890  if (!out)
891  out = MComplex("", n);
892  auto par =
893  std::static_pointer_cast<Value<std::vector<std::complex<double>>>>(out);
894  auto &results = par->values(); // reference
895  if (results.size() != n) {
896  results.resize(n);
897  }
898 
899  std::transform(pstl::execution::par_unseq,
900  paras.mComplexValue(0)->operator()().begin(),
901  paras.mComplexValue(0)->operator()().end(), results.begin(),
902  [](std::complex<double> c) { return std::conj(c); });
903  break;
904  } // end multi complex
905  case ParType::COMPLEX: {
906  // output complex: input must be a complex
907  if (nC != 1 || nMC)
908  throw BadParameter("ComplexConjugate::execute() | COMPLEX: Number and/or "
909  "types do not match");
910  if (!out)
911  out = std::make_shared<Value<std::complex<double>>>();
912  auto par = std::static_pointer_cast<Value<std::complex<double>>>(out);
913  auto &result = par->values(); // reference
914  result = std::conj(paras.complexValue(0)->value()); // reset
915  break;
916  } // end double
917  default: {
918  throw BadParameter("ComplexConjugate::execute() | Parameter of type " +
919  std::to_string(checkType) + " can not be handled");
920  }
921  } // end switch
922 };
923 
924 void AbsSquare::execute(ParameterList &paras, std::shared_ptr<Parameter> &out) {
925  if (out && checkType != out->type())
926  throw BadParameter("AbsSquare::SquareRoot() | Parameter type mismatch!");
927 
928  size_t nMC = paras.mComplexValues().size();
929  size_t nMD = paras.mDoubleValues().size();
930  size_t nMI = paras.mIntValues().size();
931  size_t nC = paras.complexValues().size();
932  // size_t nD = paras.doubleValues().size() +
933  // paras.doubleParameters().size();
934  size_t nI = paras.intValues().size();
935 
936  if (paras.numParameters() + paras.numValues() != 1)
937  throw std::runtime_error("AbsSquare::execute() | Input parameter list "
938  "contains more than one parameter!");
939 
940  switch (checkType) {
941 
942  case ParType::MDOUBLE: {
943  if (nMD == 1) {
944  size_t n = paras.mDoubleValue(0)->values().size();
945  if (!out)
946  out = MDouble("", n);
947  auto par = std::static_pointer_cast<Value<std::vector<double>>>(out);
948  auto &results = par->values(); // reference
949  if (results.size() != n) {
950  results.resize(n);
951  }
952  std::transform(paras.mDoubleValue(0)->operator()().begin(),
953  paras.mDoubleValue(0)->operator()().end(), results.begin(),
954  [](double c) { return std::norm(c); });
955  } else if (nMC == 1) {
956  size_t n = paras.mComplexValue(0)->values().size();
957  if (!out)
958  out = MDouble("", n);
959  auto par = std::static_pointer_cast<Value<std::vector<double>>>(out);
960  auto &results = par->values(); // reference
961  if (results.size() != n) {
962  results.resize(n);
963  }
964  std::transform(pstl::execution::par_unseq,
965  paras.mComplexValue(0)->values().begin(),
966  paras.mComplexValue(0)->values().end(), results.begin(),
967  [](std::complex<double> c) { return std::norm(c); });
968  } else if (nMI == 1) {
969  size_t n = paras.mIntValue(0)->values().size();
970  if (!out)
971  out = MDouble("", n);
972  auto par = std::static_pointer_cast<Value<std::vector<double>>>(out);
973  auto &results = par->values(); // reference
974  if (results.size() != n) {
975  results.resize(n);
976  }
977  std::transform(pstl::execution::par_unseq,
978  paras.mIntValue(0)->operator()().begin(),
979  paras.mIntValue(0)->operator()().end(), results.begin(),
980  [](int c) { return std::norm(c); });
981  } else {
982  throw BadParameter("AbsSquare::execute() | MDOUBLE: Number and/or "
983  "types do not match");
984  }
985  break;
986  } // end multi double
987  case ParType::MINTEGER: {
988  if (nMI != 1)
989  throw BadParameter("AbsSquare::execute() | MINTEGER: Number and/or "
990  "types do not match");
991  size_t n = paras.mIntValue(0)->values().size();
992  if (!out)
993  out = MInteger("", n);
994  auto par = std::static_pointer_cast<Value<std::vector<int>>>(out);
995  auto &results = par->values(); // reference
996  if (results.size() != n) {
997  results.resize(n);
998  }
999  std::transform(pstl::execution::par_unseq,
1000  paras.mDoubleValue(0)->operator()().begin(),
1001  paras.mDoubleValue(0)->operator()().end(), results.begin(),
1002  [](int c) { return std::norm(c); });
1003  break;
1004  }
1005  case ParType::INTEGER: {
1006  if (nI != 1)
1007  throw BadParameter("AbsSquare::execute() | INTEGER: Number and/or "
1008  "types do not match");
1009  out = std::shared_ptr<Parameter>(
1010  new Value<int>(out->name(), std::norm(paras.intValue(0)->value())));
1011  break;
1012  }
1013  case ParType::DOUBLE: {
1014  if (paras.doubleValues().size()) {
1015  out = std::shared_ptr<Parameter>(new Value<double>(
1016  out->name(), std::norm(paras.doubleValue(0)->value())));
1017  } else if (paras.doubleParameters().size()) {
1018  out = std::shared_ptr<Parameter>(new Value<double>(
1019  out->name(), std::norm(paras.doubleParameter(0)->value())));
1020  } else if (nC) {
1021  out = std::shared_ptr<Parameter>(new Value<double>(
1022  out->name(), std::norm(paras.complexValue(0)->value())));
1023  } else {
1024  throw BadParameter("AbsSquare::execute() | DOUBLE: Number and/or "
1025  "types do not match");
1026  }
1027  break;
1028  } // end double
1029  default: {
1030  throw BadParameter("AbsSquare::execute() | Parameter of type " +
1031  std::to_string(checkType) + " can not be handled");
1032  }
1033  } // end switch
1034 };
1035 
1036 } // namespace FunctionTree
1037 } // namespace ComPWA
virtual std::shared_ptr< Value< int > > intValue(size_t i)
Parameter not existing.
Definition: Exceptions.hpp:62
virtual void execute(ParameterList &paras, std::shared_ptr< Parameter > &out)
Strategy execution.
Definition: Functions.cpp:55
virtual void execute(ParameterList &paras, std::shared_ptr< Parameter > &out)
Strategy execution.
Definition: Functions.cpp:17
virtual void execute(ParameterList &paras, std::shared_ptr< Parameter > &out)
Strategy execution.
Definition: Functions.cpp:548
virtual void execute(ParameterList &paras, std::shared_ptr< Parameter > &out)
Strategy execution.
Definition: Functions.cpp:924
std::shared_ptr< Value< std::vector< double > > > MDouble(std::string name, size_t s, double el=0.)
Definition: Value.hpp:134
virtual std::vector< std::shared_ptr< Value< std::vector< int > > > > & mIntValues()
virtual void execute(ParameterList &paras, std::shared_ptr< Parameter > &out)
Strategy execution.
Definition: Functions.cpp:798
virtual void execute(ParameterList &paras, std::shared_ptr< Parameter > &out)
Strategy execution.
Definition: Functions.cpp:347
This file contains Functions implementing the Strategy interface so they can be used inside a node of...
virtual std::size_t numValues() const
virtual std::shared_ptr< Value< std::vector< std::complex< double > > > > mComplexValue(size_t i) const
virtual std::vector< std::shared_ptr< Value< std::vector< double > > > > & mDoubleValues()
virtual std::size_t numParameters() const
virtual void execute(ParameterList &paras, std::shared_ptr< Parameter > &out)
Strategy execution.
Definition: Functions.cpp:865
std::shared_ptr< Value< std::vector< int > > > MInteger(std::string name, size_t s, int el=0.)
Definition: Value.hpp:147
virtual std::vector< std::shared_ptr< Value< std::complex< double > > > > & complexValues()
std::shared_ptr< Value< std::vector< std::complex< double > > > > MComplex(std::string name, size_t s, std::complex< double > el=std::complex< double >(0., 0.))
Definition: Value.hpp:120
virtual std::shared_ptr< FitParameter > doubleParameter(size_t i) const
virtual std::vector< std::shared_ptr< Value< std::vector< std::complex< double > > > > > & mComplexValues()
virtual std::vector< std::shared_ptr< Value< double > > > & doubleValues()
virtual std::vector< std::shared_ptr< FitParameter > > & doubleParameters()
virtual std::vector< std::shared_ptr< Value< int > > > & intValues()
virtual std::shared_ptr< Value< std::vector< int > > > mIntValue(size_t i) const
KahanSummation KahanSum(KahanSummation accumulation, double value)
KahanSummation keeps track of lost bits and reduced the uncertainty in the summation of many large/sm...
Definition: Functions.cpp:98
virtual void execute(ParameterList &paras, std::shared_ptr< Parameter > &out)
Strategy execution.
Definition: Functions.cpp:714
virtual std::shared_ptr< Value< std::complex< double > > > complexValue(size_t i) const
virtual T & values()
Reference on the value.
Definition: Value.hpp:49
This class provides a list of parameters and values of different types.
virtual std::shared_ptr< Value< std::vector< double > > > mDoubleValue(size_t i) const
virtual std::shared_ptr< Value< double > > doubleValue(size_t i) const
virtual void execute(ParameterList &paras, std::shared_ptr< Parameter > &out)
Strategy execution.
Definition: Functions.cpp:631
virtual void execute(ParameterList &paras, std::shared_ptr< Parameter > &out)
Add all values.
Definition: Functions.cpp:107