packages feed

casadi-bindings-3.4.5.0: cbits/casadi_bindings.cpp

#include "math.h"
#include <iostream>
#include "casadi/core/core.hpp"
#include "casadi/core/callback.hpp"

#include "HsFFI.h"

// #define DEBUG_WOO

#ifdef DEBUG_WOO
#define debug(msg)    \
  std::cerr << "* " << msg << std::endl;
#else
#define debug(msg){}
#endif

typedef std::vector<casadi::DM>*
  (*hs_callback_thing)(std::vector<casadi::DM*>*,
                       std::map<std::string, casadi::GenericType*>*);

class HaskellCallback : public casadi::Callback {
public:
  HaskellCallback(const std::string &name,
                  HsFunPtr hsfp,
                  std::vector<casadi::Sparsity> &sp_in_,
                  std::vector<casadi::Sparsity> &sp_out_) : cb_name(name), sp_in(sp_in_), sp_out(sp_out_) {
    debug(cb_name << ": HaskellCallback constructor called...");
    construct(name);
    hs_fun_ptr = hsfp;
  }

  // Initialize the object
  void init() override {
    debug(cb_name << ": HaskellCallback::init() called...");
  }

  // Number of inputs and outputs
  long long get_n_in() override { return sp_in.size(); }
  long long get_n_out() override { return sp_out.size(); }

  casadi::Sparsity get_sparsity_in(long long i) override {
    debug(cb_name << ": HaskellCallback::get_sparsity_in called");
    return sp_in[i];
  }
  casadi::Sparsity get_sparsity_out(long long i) override {
    debug(cb_name << ": HaskellCallback::get_sparsity_out called");
    return sp_out[i];
  }

  std::vector<casadi::DM> eval(const std::vector<casadi::DM>& args) const override {
    debug(cb_name << ": HaskellCallback::eval() called. Converting inputs to haskell-friendly...");
    std::vector<casadi::DM*> *hsArgs = new std::vector<casadi::DM*>();
    for (size_t k = 0; k < args.size(); k++) {
      hsArgs->push_back(new casadi::DM(args[k]));
    }

    std::map<std::string, casadi::GenericType> latestStats = stats();
    debug(cb_name << ": HaskellCallback::eval() called. Converting stats to haskell-friendly...");
    std::map<std::string, casadi::GenericType*> *hsStats =
      new std::map<std::string, casadi::GenericType*>();
    std::map<std::string, casadi::GenericType>::iterator it;
    for (it = latestStats.begin(); it != latestStats.end(); it++) {
      std::string key = it->first;
      casadi::GenericType *val = new casadi::GenericType(it->second);
      std::pair<std::string, casadi::GenericType*> keyVal(key, val);
      hsStats->insert(keyVal);
    }

    debug(cb_name << ": HaskellCallback::eval() calling back to the haskell function...");
    std::vector<casadi::DM>* hsRet = ((hs_callback_thing)hs_fun_ptr)(hsArgs, hsStats);

    debug(cb_name << ": HaskellCallback::call() converting haskell outputs to casadi-friendly...");
    std::vector<casadi::DM> ret;
    for (size_t k = 0; k < hsRet->size(); k++) {
      ret.push_back((*hsRet)[k]);
    }
    delete hsRet;

    debug(cb_name << ": HaskellCallback::call() return size: " << ret.size());
    debug(cb_name << ": HaskellCallback::call() returning casadi outputs to casadi...");
    return ret;
  }

  ~HaskellCallback() {
    // free the haskell FunPtr
    debug(cb_name << ": HaskellCallback destructor started");
    hs_free_fun_ptr(hs_fun_ptr);
    debug(cb_name << ": HaskellCallback destructor finished");
  }
  std::string cb_name;
private:
  HsFunPtr hs_fun_ptr;
  std::vector<casadi::Sparsity> sp_in;
  std::vector<casadi::Sparsity> sp_out;

}; // class HaskellCallback


extern "C"
void delete_haskell_callback(casadi::Function *haskell_callback0);
void delete_haskell_callback(casadi::Function *haskell_callback0) {
  HaskellCallback *haskell_callback = static_cast<HaskellCallback*>(haskell_callback0);
  const std::string name = haskell_callback->cb_name; // copy so we don't use after delete
  debug(name << ": deleting haskell callback...");
  delete haskell_callback;
  debug(name << ": haskell callback deleted");
}

extern "C"
casadi::Function * new_haskell_callback(const std::string *cb_name,
                                        HsFunPtr hsfp,
                                        std::vector<casadi::Sparsity*> *sp_in,
                                        std::vector<casadi::Sparsity*> *sp_out);
casadi::Function * new_haskell_callback(const std::string *cb_name,
                                        HsFunPtr hsfp,
                                        std::vector<casadi::Sparsity*> *sp_in_p,
                                        std::vector<casadi::Sparsity*> *sp_out_p) {
  debug(*cb_name << ": new_callback_haskell called. Unpacking sparsity_in/sparsity_out");
  std::vector<casadi::Sparsity> sp_in;
  for (size_t k=0; k<sp_in_p->size(); k++) {
    sp_in.push_back(*((*sp_in_p)[k]));
  }
  std::vector<casadi::Sparsity> sp_out;
  for (size_t k=0; k<sp_out_p->size(); k++) {
    sp_out.push_back(*((*sp_out_p)[k]));
  }
  return static_cast<casadi::Function*>(new HaskellCallback(*cb_name, hsfp, sp_in, sp_out));
}

extern "C"
std::vector<casadi::DM>* to_dm_vec(std::vector<casadi::DM*> *x);
std::vector<casadi::DM>* to_dm_vec(std::vector<casadi::DM*> *x) {
  std::vector<casadi::DM> *ret = new std::vector<casadi::DM>();
  for (size_t k=0; k<x->size(); k++) {
    ret->push_back(*((*x)[k]));
  }
  return ret;
}

extern "C" double c_fmod(double x, double y);
double c_fmod(double x, double y) {
  return fmod(x, y);
}

extern "C" float c_fmodf(float x, float y);
float c_fmodf(float x, float y) {
  return fmodf(x, y);
}

extern "C"
void hs_call_casadi_function_with_pointers(
  std::string ** err_msg,
  casadi::Function &f,
  double ** arg, int narg,
  double ** res, int nres) {
  try {
    // setup inputs
    std::vector<const double*> argv(narg);
    for (int k = 0; k < narg; k++) {
      argv[k] = arg[k];
    }

    // setup outputs
    std::vector<double*> resv(nres);
    for (int k = 0; k < nres; k++) {
      resv[k] = res[k];
    }

    // call the function
    f(argv, resv);
  } catch (std::exception& ex) {
    *err_msg = new std::string(ex.what());
  }
}