5 #ifndef LODESTAR_BLOCK_HPP
6 #define LODESTAR_BLOCK_HPP
11 #include "BlockBase.hpp"
13 #include "BlockTraits.hpp"
14 #include "Lodestar/aux/TemplateTools.hpp"
15 #include "Lodestar/aux/AlwaysFalse.hpp"
19 #include <ginac/ginac.h>
44 template<
typename TInputsList,
typename TOutputsList,
typename TParametersList = BlockProto::empty>
46 :
public BlockBase<Block<TInputsList, TOutputsList, TParametersList>> {
69 template<
typename... TInputs,
typename... TOutputs,
typename... TParameters>
72 ::std::tuple<TInputs...>,
73 ::std::tuple<TOutputs...>,
74 ::std::tuple<TParameters...>
77 ::std::tuple<TInputs...>,
78 ::std::tuple<TOutputs...>,
79 ::std::tuple<TParameters...>>
85 ::std::tuple<TInputs...>,
86 ::std::tuple<TOutputs...>,
87 ::std::tuple<TParameters...>
92 using Inputs = ::std::tuple<typename ls::aux::TemplateTools::wrap<TInputs, Signal>::type...>;
96 using Outputs = ::std::tuple<typename ls::aux::TemplateTools::wrap<TOutputs, Signal>::type...>;
98 using Params = ::std::tuple<TParameters...>;
104 kIns =
sizeof...(TInputs),
105 kOuts =
sizeof...(TOutputs),
106 kPars =
sizeof...(TParameters)
126 int inputSlotCounter = 0;
127 auto primeInputSignal = [&](SignalBase *sb) {
129 sb->slotId = inputSlotCounter++;
135 int outputSlotCounter = 0;
136 auto primeOutputSignal = [&](SignalBase *sb) {
138 sb->slotId = outputSlotCounter++;
144 ls::aux::TemplateTools::Executors::forEachPointer(inputs,
146 ls::aux::TemplateTools::Executors::forEachPointer(outputs,
165 template<
size_t TIdx,
166 typename ::std::enable_if<((TIdx >= 0) && (TIdx < kIns))>::type * =
nullptr>
167 typename ::std::tuple_element<TIdx, Inputs>::type &
getInput()
169 return ::std::get<TIdx>(inputs);
177 template<
size_t TIdx,
178 typename ::std::enable_if<!((TIdx >= 0) && (TIdx < kIns))>::type * =
nullptr>
179 typename ::std::tuple_element<TIdx, Inputs>::type &
getInput()
181 static_assert(((TIdx >= 0) && (TIdx < kIns)),
182 "Input index out of bounds.");
190 template<
size_t TIdx,
191 typename ::std::enable_if<((TIdx >= 0) && (TIdx < kIns))>::type * =
nullptr>
192 const typename ::std::tuple_element<TIdx, Inputs>::type &
195 return ::std::get<TIdx>(inputs);
203 template<
size_t TIdx,
204 typename ::std::enable_if<!((TIdx >= 0) && (TIdx < kIns))>::type * =
nullptr>
205 const typename ::std::tuple_element<TIdx, Inputs>::type &
208 static_assert(((TIdx >= 0) && (TIdx < kIns)),
209 "Input index out of bounds.");
219 template<
size_t TIdx,
220 typename ::std::enable_if<((TIdx >= 0) && (TIdx < kIns))>::type * =
nullptr>
221 typename ::std::tuple_element<TIdx, Inputs>::type &
i()
223 return getInput<TIdx>();
231 template<
size_t TIdx,
232 typename ::std::enable_if<!((TIdx >= 0) && (TIdx < kIns))>::type * =
nullptr>
233 typename ::std::tuple_element<TIdx, Inputs>::type &
i()
235 static_assert(((TIdx >= 0) && (TIdx < kIns)),
236 "Input index out of bounds.");
246 template<
size_t TIdx,
247 typename ::std::enable_if<((TIdx >= 0) && (TIdx < kIns))>::type * =
nullptr>
248 const typename ::std::tuple_element<TIdx, Inputs>::type &
i()
const
250 return getInput<TIdx>();
258 template<
size_t TIdx,
259 typename ::std::enable_if<!((TIdx >= 0) && (TIdx < kIns))>::type * =
nullptr>
260 const typename ::std::tuple_element<TIdx, Inputs>::type &
i()
const
262 static_assert(((TIdx >= 0) && (TIdx < kIns)),
263 "Input index out of bounds.");
273 template<
size_t TIdx,
274 typename ::std::enable_if<((TIdx >= 0) && (TIdx < kOuts))>::type * =
nullptr>
275 typename ::std::tuple_element<TIdx, Outputs>::type &
getOutput()
277 return ::std::get<TIdx>(outputs);
285 template<
size_t TIdx,
286 typename ::std::enable_if<!((TIdx >= 0) && (TIdx < kOuts))>::type * =
nullptr>
287 typename ::std::tuple_element<TIdx, Outputs>::type &
getOutput()
289 static_assert(((TIdx >= 0) && (TIdx < kOuts)),
290 "Output index out of bounds.");
298 template<
size_t TIdx,
299 typename ::std::enable_if<((TIdx >= 0) && (TIdx < kOuts))>::type * =
nullptr>
300 const typename ::std::tuple_element<TIdx, Outputs>::type &
303 return ::std::get<TIdx>(outputs);
311 template<
size_t TIdx,
312 typename ::std::enable_if<!((TIdx >= 0) && (TIdx < kOuts))>::type * =
nullptr>
313 const typename ::std::tuple_element<TIdx, Outputs>::type &
316 static_assert(((TIdx >= 0) && (TIdx < kOuts)),
317 "Output index out of bounds.");
327 template<
size_t TIdx,
328 typename ::std::enable_if<((TIdx >= 0) && (TIdx < kOuts))>::type * =
nullptr>
329 typename ::std::tuple_element<TIdx, Outputs>::type &
o()
331 return getOutput<TIdx>();
339 template<
size_t TIdx,
340 typename ::std::enable_if<!((TIdx >= 0) && (TIdx < kOuts))>::type * =
nullptr>
341 typename ::std::tuple_element<TIdx, Outputs>::type &
o()
343 static_assert(((TIdx >= 0) && (TIdx < kOuts)),
344 "Output index out of bounds.");
354 template<
size_t TIdx,
355 typename ::std::enable_if<((TIdx >= 0) && (TIdx < kOuts))>::type * =
nullptr>
356 const typename ::std::tuple_element<TIdx, Outputs>::type &
o()
const
358 return getOutput<TIdx>();
366 template<
size_t TIdx,
367 typename ::std::enable_if<!((TIdx >= 0) && (TIdx < kOuts))>::type * =
nullptr>
368 const typename ::std::tuple_element<TIdx, Outputs>::type &
o()
const
370 static_assert(((TIdx >= 0) && (TIdx < kOuts)),
371 "Output index out of bounds.");
381 template<
size_t TIdx,
382 typename ::std::enable_if<((TIdx >= 0) && (TIdx < kPars))>::type * =
nullptr>
383 typename ::std::tuple_element<TIdx, Params>::type &
getParam()
385 return ::std::get<TIdx>(params);
393 template<
size_t TIdx,
394 typename ::std::enable_if<!((TIdx >= 0) && (TIdx < kPars))>::type * =
nullptr>
395 typename ::std::tuple_element<TIdx, Params>::type &
getParam()
397 static_assert(((TIdx >= 0) && (TIdx < kPars)),
398 "Parameter index out of bounds.");
406 template<
size_t TIdx,
407 typename ::std::enable_if<((TIdx >= 0) && (TIdx < kPars))>::type * =
nullptr>
408 const typename ::std::tuple_element<TIdx, Params>::type &
411 return ::std::get<TIdx>(params);
419 template<
size_t TIdx,
420 typename ::std::enable_if<!((TIdx >= 0) && (TIdx < kPars))>::type * =
nullptr>
421 const typename ::std::tuple_element<TIdx, Params>::type &
424 static_assert(((TIdx >= 0) && (TIdx < kPars)),
425 "Parameter index out of bounds.");
435 template<
size_t TIdx,
436 typename ::std::enable_if<((TIdx >= 0) && (TIdx < kPars))>::type * =
nullptr>
437 typename ::std::tuple_element<TIdx, Params>::type &
p()
439 return getParam<TIdx>();
447 template<
size_t TIdx,
448 typename ::std::enable_if<!((TIdx >= 0) && (TIdx < kPars))>::type * =
nullptr>
449 typename ::std::tuple_element<TIdx, Params>::type &
p()
451 static_assert(((TIdx >= 0) && (TIdx < kPars)),
452 "Parameter index out of bounds.");
462 template<
size_t TIdx,
463 typename ::std::enable_if<((TIdx >= 0) && (TIdx < kPars))>::type * =
nullptr>
464 const typename ::std::tuple_element<TIdx, Params>::type &
p()
const
466 return getParam<TIdx>();
474 template<
size_t TIdx,
475 typename ::std::enable_if<!((TIdx >= 0) && (TIdx < kPars))>::type * =
nullptr>
476 const typename ::std::tuple_element<TIdx, Params>::type &
p()
const
478 static_assert(((TIdx >= 0) && (TIdx < kPars)),
479 "Parameter index out of bounds.");
488 return equation(*
this);
493 const ::std::array<GiNaC::ex, kIns> &inputSymbols()
496 for (
int i = 0; i < kIns; i++)
497 inputSymbols_[i] = GiNaC::symbol{
"blk" + ::std::to_string(
id) +
"_i_" + ::std::to_string(i),
498 "\\text{BLK}^{i, " + ::std::to_string(i) +
"}_{" + ::std::to_string(
id) +
504 return inputSymbols_;
507 const ::std::array<GiNaC::ex, kOuts> &outputSymbols()
509 if (!isInitOutput_) {
510 for (
int i = 0; i < kOuts; i++)
511 outputSymbols_[i] = GiNaC::symbol{
"blk" + ::std::to_string(
id) +
"_o_" + ::std::to_string(i),
512 "\\text{BLK}^{o, " + ::std::to_string(i) +
"}_{" + ::std::to_string(
id) +
515 isInitOutput_ =
true;
518 return outputSymbols_;
521 const ::std::array<GiNaC::ex, kPars> ¶meterSymbols()
523 if (!isInitParameter_) {
524 for (
int i = 0; i < kPars; i++)
525 parameterSymbols_[i] = GiNaC::symbol{
"blk" + ::std::to_string(
id) +
"_p_" + ::std::to_string(i),
526 "\\text{BLK}^{o, " + ::std::to_string(i) +
"}_{" + ::std::to_string(
id) +
529 isInitParameter_ =
true;
532 return parameterSymbols_;
543 static const unsigned blkFunc_NPARAMS = 1;
545 template<
typename ...T, typename ::std::enable_if<
sizeof...(T) == kIns>::type * =
nullptr>
546 const GiNaC::function blkf(
const T &...p)
548 return GiNaC::function(BlockProto::serial, ::std::vector<GiNaC::ex>{GiNaC::ex(p)..., GiNaC::numeric{
id}});
551 template<
typename ...T, typename ::std::enable_if<
sizeof...(T) != kIns>::type * =
nullptr>
552 const GiNaC::function blkf(
const T &...p)
554 static_assert(
sizeof...(T) == blkFunc_NPARAMS,
555 "Incorrect number of arguments provided to symbolic function.");
557 return GiNaC::function(BlockProto::serial, ::std::vector<GiNaC::ex>{GiNaC::ex(p)...});
561 ::std::array<int, kIns> &inputSymbols()
563 static_assert(
always_false<::std::array<int, kIns>>::value,
"GiNaC use is not enabled. Please compile with LS_USE_GINAC flag.");
565 static ::std::array<int, kIns> arr;
569 ::std::array<int, kIns> &outputSymbols()
571 static_assert(
always_false<::std::array<int, kIns>>::value,
"GiNaC use is not enabled. Please compile with LS_USE_GINAC flag.");
573 static ::std::array<int, kIns> arr;
577 ::std::array<int, kIns> ¶meterSymbols()
579 static_assert(
always_false<::std::array<int, kIns>>::value,
"GiNaC use is not enabled. Please compile with LS_USE_GINAC flag.");
581 static ::std::array<int, kIns> arr;
598 bool isInitInput_ =
false;
599 bool isInitOutput_ =
false;
600 bool isInitParameter_ =
false;
602 ::std::array<GiNaC::ex, kIns> inputSymbols_;
603 ::std::array<GiNaC::ex, kOuts> outputSymbols_;
604 ::std::array<GiNaC::ex, kPars> parameterSymbols_;
608 template<
typename... TInputs,
609 typename... TOutputs,
610 typename... TParameters>
613 ::std::tuple<TInputs...>,
614 ::std::tuple<TOutputs...>,
615 ::std::tuple<TParameters...>
623 ::std::tuple<TInputs...>,
624 ::std::tuple<TOutputs...>,
625 ::std::tuple<TParameters...>
627 using Base =
typename type::Base;
629 static const constexpr
int kIns = type::Base::kIns;
630 static const constexpr
int kOuts = type::Base::kOuts;
631 static const constexpr
int kPars = type::Base::kPars;
635 static ::std::unordered_map<
unsigned int, ::std::function<GiNaC::ex(::std::vector<GiNaC::ex>)>>
636 symbolicEvalFunctionMap{}, symbolicEvalfFunctionMap{}, symbolicConjugateFunctionMap{}, symbolicRealFunctionMap{},
637 symbolicImagFunctionMap{}, symbolicExpandFunctionMap{}, symbolicDerivFunctionMap{}, symbolicExplDerivFunctionMap{},
638 symbolicPowerFunctionMap{}, symbolicSeriesFunctionMap{}, symbolicPrintFunctionMap{}, symbolicInfoFunctionMap{};
640 static GiNaC::ex symbolicEval(const ::std::vector<GiNaC::ex> &args)
642 return symbolicEvalFunctionMap[GiNaC::ex_to<GiNaC::numeric>(args.back()).to_int()](
643 ::std::vector<GiNaC::ex>{args.begin(), args.end() - 1});
646 static GiNaC::ex symbolicEvalf(const ::std::vector<GiNaC::ex> &args)
648 return symbolicEvalfFunctionMap[GiNaC::ex_to<GiNaC::numeric>(args.back()).to_int()](
649 ::std::vector<GiNaC::ex>{args.begin(), args.end() - 1});
652 static GiNaC::ex symbolicConjugate(const ::std::vector<GiNaC::ex> &args)
654 return symbolicConjugateFunctionMap[GiNaC::ex_to<GiNaC::numeric>(args.back()).to_int()](
655 ::std::vector<GiNaC::ex>{args.begin(), args.end() - 1});
658 static GiNaC::ex symbolicReal(const ::std::vector<GiNaC::ex> &args)
660 return symbolicRealFunctionMap[GiNaC::ex_to<GiNaC::numeric>(args.back()).to_int()](
661 ::std::vector<GiNaC::ex>{args.begin(), args.end() - 1});
664 static GiNaC::ex symbolicImag(const ::std::vector<GiNaC::ex> &args)
666 return symbolicImagFunctionMap[GiNaC::ex_to<GiNaC::numeric>(args.back()).to_int()](
667 ::std::vector<GiNaC::ex>{args.begin(), args.end() - 1});
670 static GiNaC::ex symbolicExpand(const ::std::vector<GiNaC::ex> &args)
672 return symbolicExpandFunctionMap[GiNaC::ex_to<GiNaC::numeric>(args.back()).to_int()](
673 ::std::vector<GiNaC::ex>{args.begin(), args.end() - 1});
676 static GiNaC::ex symbolicDeriv(const ::std::vector<GiNaC::ex> &args)
678 return symbolicDerivFunctionMap[GiNaC::ex_to<GiNaC::numeric>(args.back()).to_int()](
679 ::std::vector<GiNaC::ex>{args.begin(), args.end() - 1});
682 static GiNaC::ex symbolicExplDeriv(const ::std::vector<GiNaC::ex> &args)
684 return symbolicExplDerivFunctionMap[GiNaC::ex_to<GiNaC::numeric>(args.back()).to_int()](
685 ::std::vector<GiNaC::ex>{args.begin(), args.end() - 1});
688 static GiNaC::ex symbolicPower(const ::std::vector<GiNaC::ex> &args)
690 return symbolicPowerFunctionMap[GiNaC::ex_to<GiNaC::numeric>(args.back()).to_int()](
691 ::std::vector<GiNaC::ex>{args.begin(), args.end() - 1});
694 static GiNaC::ex symbolicSeries(const ::std::vector<GiNaC::ex> &args)
696 return symbolicSeriesFunctionMap[GiNaC::ex_to<GiNaC::numeric>(args.back()).to_int()](
697 ::std::vector<GiNaC::ex>{args.begin(), args.end() - 1});
700 static GiNaC::ex symbolicPrint(const ::std::vector<GiNaC::ex> &args)
702 return symbolicPrintFunctionMap[GiNaC::ex_to<GiNaC::numeric>(args.back()).to_int()](
703 ::std::vector<GiNaC::ex>{args.begin(), args.end() - 1});
706 static GiNaC::ex symbolicInfo(const ::std::vector<GiNaC::ex> &args)
708 return symbolicInfoFunctionMap[GiNaC::ex_to<GiNaC::numeric>(args.back()).to_int()](
709 ::std::vector<GiNaC::ex>{args.begin(), args.end() - 1});
716 #endif //LODESTAR_BLOCK_HPP