13  static void store_output(
auto& self, 
const ossia::value& v)
 
   17      case ossia::val_type::NONE:
 
   19      case ossia::val_type::FLOAT:
 
   20        self.po = *v.target<
float>();
 
   22      case ossia::val_type::VEC2F: {
 
   23        if constexpr(
requires { self.pov; })
 
   25          auto& vec = *v.target<ossia::vec2f>();
 
   26          self.pov.assign(vec.begin(), vec.end());
 
   30      case ossia::val_type::VEC3F: {
 
   31        if constexpr(
requires { self.pov; })
 
   33          auto& vec = *v.target<ossia::vec3f>();
 
   34          self.pov.assign(vec.begin(), vec.end());
 
   38      case ossia::val_type::VEC4F: {
 
   39        if constexpr(
requires { self.pov; })
 
   41          auto& vec = *v.target<ossia::vec4f>();
 
   42          self.pov.assign(vec.begin(), vec.end());
 
   46      case ossia::val_type::LIST: {
 
   47        if constexpr(
requires { self.pov; })
 
   49          auto& arr = *v.target<std::vector<ossia::value>>();
 
   54              self.pov.push_back(ossia::convert<float>(v));
 
   65  static void exec_scalar(
State& self, value_output_callback& output)
 
   67    auto res = self.expr.result();
 
   70    store_output(self, res);
 
   75  static void exec_polyphonic(
State& self, value_output_callback& output)
 
   77    for(
auto& e : self.expressions)
 
   79      auto res = e.expr.result();
 
   81      if constexpr(
requires { e.x; })
 
   89  exec_array(
State& self, value_output_callback& output, 
bool vector_size_did_change)
 
   94    if(vector_size_did_change)
 
   96      self.expr.rebase_vector(
"xv", self.xv);
 
   97      self.expr.recompile();
 
  100    auto res = self.expr.result();
 
  101    store_output(self, res);
 
  105      bool old_prev = self.pxv.size();
 
  106      self.pxv.assign(self.xv.begin(), self.xv.end());
 
  107      bool new_prev = self.pxv.size();
 
  109      if(old_prev != new_prev)
 
  111        self.expr.rebase_vector(
"pxv", self.pxv);
 
  112        self.expr.recompile();
 
  116    output(std::move(res));
 
  119  static void run_scalar(
 
  120      const ossia::value& v, value_output_callback& output, 
const halp::tick_flicks& tk,
 
  123    setMathExpressionTiming(
 
  124        self, tk.start_in_flicks, self.last_value_time, tk.relative_position);
 
  125    self.last_value_time = tk.start_in_flicks;
 
  129      case ossia::val_type::NONE:
 
  131      case ossia::val_type::IMPULSE:
 
  133      case ossia::val_type::INT:
 
  134        self.x = *v.target<
int>();
 
  136      case ossia::val_type::FLOAT:
 
  137        self.x = *v.target<
float>();
 
  139      case ossia::val_type::BOOL:
 
  140        self.x = *v.target<
bool>() ? 1.f : 0.f;
 
  142      case ossia::val_type::STRING:
 
  143        self.x = ossia::convert<float>(v);
 
  145      case ossia::val_type::VEC2F:
 
  146        self.x = (*v.target<ossia::vec2f>())[0];
 
  148      case ossia::val_type::VEC3F:
 
  149        self.x = (*v.target<ossia::vec3f>())[0];
 
  151      case ossia::val_type::VEC4F:
 
  152        self.x = (*v.target<ossia::vec4f>())[0];
 
  154      case ossia::val_type::LIST: {
 
  155        auto& arr = *v.target<std::vector<ossia::value>>();
 
  157          self.x = ossia::convert<float>(arr[0]);
 
  160      case ossia::val_type::MAP: {
 
  161        auto& arr = *v.target<ossia::value_map_type>();
 
  163          self.x = ossia::convert<float>(arr.begin()->second);
 
  168    GenericMathMapping::exec_scalar(self, output);
 
  171  static bool resize(
const std::string& expr, 
State& self, 
int sz)
 
  173    if(std::ssize(self.expressions) == sz && expr == self.last_expression)
 
  176    self.expressions.resize(sz);
 
  179    for(
auto& e : self.expressions)
 
  181      e.init(self.cur_time, self.cur_deltatime, self.cur_pos, self.count);
 
  183      if(!e.expr.set_expression(expr))
 
  186          UINT64_C(0xda3e39cb94b95bdb), UINT64_C(0x853c49e6748fea9b) * (1 + i));
 
  188    self.last_expression = expr;
 
  192  static void run_polyphonic(
 
  193      int size, value_output_callback& output, 
const std::string& expr,
 
  194      const halp::tick_flicks& tk, 
State& self)
 
  197       || (expr.find(
":=") != std::string::npos && expr.find(
"po") != std::string::npos))
 
  199      size = std::clamp(size, 0, 1024);
 
  200      resize(expr, self, size);
 
  202      setMathExpressionTiming(
 
  203          self, tk.start_in_flicks, self.last_value_time, tk.relative_position);
 
  204      self.last_value_time = tk.start_in_flicks;
 
  206      GenericMathMapping::exec_polyphonic(self, output);
 
  208      std::vector<ossia::value> res;
 
  209      res.resize(self.expressions.size());
 
  211      for(
int i = 0; i < self.expressions.size(); i++)
 
  212        res[i] = (
float)self.expressions[i].po;
 
  214      output(std::move(res));
 
  218      resize(expr, self, 1);
 
  219      setMathExpressionTiming(
 
  220          self, tk.start_in_flicks, self.last_value_time, tk.relative_position);
 
  221      self.last_value_time = tk.start_in_flicks;
 
  223      std::vector<ossia::value> res;
 
  226      for(
int i = 0; i < size; i++)
 
  228        auto& e = self.expressions[0];
 
  230        res[i] = e.expr.result();
 
  234      output(std::move(res));
 
  238  static void run_polyphonic(
 
  239      const ossia::value& value, value_output_callback& output, 
const std::string& expr,
 
  240      const halp::tick_flicks& tk, 
State& self)
 
  242    setMathExpressionTiming(
 
  243        self, tk.start_in_flicks, self.last_value_time, tk.relative_position);
 
  244    self.last_value_time = tk.start_in_flicks;
 
  257    switch(value.get_type())
 
  259      case ossia::val_type::NONE:
 
  261      case ossia::val_type::IMPULSE:
 
  263      case ossia::val_type::INT:
 
  264        if(!resize(expr, self, 1))
 
  266        self.expressions[0].x = *value.target<
int>();
 
  268      case ossia::val_type::FLOAT:
 
  269        if(!resize(expr, self, 1))
 
  271        self.expressions[0].x = *value.target<
float>();
 
  273      case ossia::val_type::BOOL:
 
  274        if(!resize(expr, self, 1))
 
  276        self.expressions[0].x = *value.target<
bool>() ? 1.f : 0.f;
 
  278      case ossia::val_type::STRING:
 
  279        if(!resize(expr, self, 1))
 
  281        self.expressions[0].x = ossia::convert<float>(value);
 
  283      case ossia::val_type::VEC2F:
 
  284        if(!resize(expr, self, 2))
 
  286        self.expressions[0].x = (*value.target<ossia::vec2f>())[0];
 
  287        self.expressions[1].x = (*value.target<ossia::vec2f>())[1];
 
  289      case ossia::val_type::VEC3F:
 
  290        if(!resize(expr, self, 3))
 
  292        self.expressions[0].x = (*value.target<ossia::vec3f>())[0];
 
  293        self.expressions[1].x = (*value.target<ossia::vec3f>())[1];
 
  294        self.expressions[2].x = (*value.target<ossia::vec3f>())[2];
 
  296      case ossia::val_type::VEC4F:
 
  297        if(!resize(expr, self, 4))
 
  299        self.expressions[0].x = (*value.target<ossia::vec4f>())[0];
 
  300        self.expressions[1].x = (*value.target<ossia::vec4f>())[1];
 
  301        self.expressions[2].x = (*value.target<ossia::vec4f>())[2];
 
  302        self.expressions[3].x = (*value.target<ossia::vec4f>())[3];
 
  304      case ossia::val_type::LIST: {
 
  305        auto& arr = *value.target<std::vector<ossia::value>>();
 
  306        const auto N = std::clamp((
int)std::ssize(arr), 0, 1024);
 
  307        if(!resize(expr, self, N))
 
  309        for(
int i = 0; i < N; i++)
 
  310          self.expressions[i].x = ossia::convert<float>(arr[i]);
 
  313      case ossia::val_type::MAP: {
 
  314        auto& arr = *value.target<ossia::value_map_type>();
 
  315        const auto N = std::clamp((
int)std::ssize(arr), 0, 1024);
 
  316        if(!resize(expr, self, N))
 
  319        for(
auto& [k, v] : arr)
 
  320          self.expressions[i++].x = ossia::convert<float>(v);
 
  325    GenericMathMapping::exec_polyphonic(self, output);
 
  327    std::vector<ossia::value> res;
 
  328    res.resize(self.expressions.size());
 
  329    for(
int i = 0; i < self.expressions.size(); i++)
 
  330      res[i] = (
float)self.expressions[i].po;
 
  333    output(std::move(res));
 
  336  static void run_array(
 
  337      const ossia::value& value, value_output_callback& output,
 
  338      const halp::tick_flicks& tk, 
State& self)
 
  348    auto array_run_scalar = [&](
float in) {
 
  349      auto old_size = self.xv.size();
 
  350      self.xv.assign(1, in);
 
  352      GenericMathMapping::exec_array(self, output, old_size != new_size);
 
  355    switch(value.get_type())
 
  357      case ossia::val_type::NONE:
 
  359      case ossia::val_type::IMPULSE:
 
  360        GenericMathMapping::exec_array(self, output, 
false);
 
  362      case ossia::val_type::INT:
 
  363        array_run_scalar(*value.target<
int>());
 
  365      case ossia::val_type::FLOAT:
 
  366        array_run_scalar(*value.target<
float>());
 
  368      case ossia::val_type::BOOL:
 
  369        array_run_scalar(*value.target<
bool>() ? 1.f : 0.f);
 
  371      case ossia::val_type::STRING:
 
  372        array_run_scalar(ossia::convert<float>(value));
 
  374      case ossia::val_type::VEC2F: {
 
  375        auto& arr = *value.target<ossia::vec2f>();
 
  376        auto old_size = self.xv.size();
 
  377        self.xv.assign(arr.begin(), arr.end());
 
  379        GenericMathMapping::exec_array(self, output, old_size != new_size);
 
  382      case ossia::val_type::VEC3F: {
 
  383        auto& arr = *value.target<ossia::vec3f>();
 
  384        auto old_size = self.xv.size();
 
  385        self.xv.assign(arr.begin(), arr.end());
 
  387        GenericMathMapping::exec_array(self, output, old_size != new_size);
 
  390      case ossia::val_type::VEC4F: {
 
  391        auto& arr = *value.target<ossia::vec4f>();
 
  392        auto old_size = self.xv.size();
 
  393        self.xv.assign(arr.begin(), arr.end());
 
  395        GenericMathMapping::exec_array(self, output, old_size != new_size);
 
  398      case ossia::val_type::LIST: {
 
  399        auto& arr = *value.target<std::vector<ossia::value>>();
 
  400        auto old_size = self.xv.size();
 
  401        self.xv.resize(arr.size());
 
  402        auto new_size = arr.size();
 
  403        for(std::size_t i = 0; i < arr.size(); i++)
 
  405          self.xv[i] = ossia::convert<float>(arr[i]);
 
  407        GenericMathMapping::exec_array(self, output, old_size != new_size);
 
  410      case ossia::val_type::MAP: {
 
  411        auto& arr = *value.target<ossia::value_map_type>();
 
  412        auto old_size = self.xv.size();
 
  413        self.xv.resize(arr.size());
 
  414        auto new_size = arr.size();
 
  416        for(
const auto& [k, v] : arr)
 
  418          self.xv[i++] = ossia::convert<float>(v);
 
  420        GenericMathMapping::exec_array(self, output, old_size != new_size);