packages feed

casadi-bindings-3.0.0.0: cbits/casadi_bindings.cpp

#include "math.h"
#include <iostream>
#include "casadi/core/core.hpp"
#include "casadi/core/function/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(HsFunPtr hsfp,
                  std::vector<casadi::Sparsity> &sp_in_,
                  std::vector<casadi::Sparsity> &sp_out_) : sp_in(sp_in_), sp_out(sp_out_) {
    debug("HaskellCallback constructor called...");
    hs_fun_ptr = hsfp;
  }

  // Creator function, creates an owning reference
  static casadi::Function create(const std::string& name,
                                 HsFunPtr hsfp,
                                 std::vector<casadi::Sparsity> &sp_in_,
                                 std::vector<casadi::Sparsity> &sp_out_,
                                 const casadi::Dict& opts=casadi::Dict()) {
    debug("HaskellCallback create called...");
    return casadi::Callback::create(name, new HaskellCallback(hsfp, sp_in_, sp_out_), opts);
  }

  // Number of inputs and outputs
  virtual int get_n_in() { return sp_in.size(); }
  virtual int get_n_out() { return sp_out.size(); }
  virtual casadi::Sparsity get_sparsity_in(int i) {
    debug("HaskellCallback::get_sparsity_in called");
    return sp_in[i];
  }
  virtual casadi::Sparsity get_sparsity_out(int i) {
    debug("HaskellCallback::get_sparsity_out called");
    return sp_out[i];
  }
  
  virtual std::vector<casadi::DM> eval(const std::vector<casadi::DM>& args) {
    debug("HaskellCallback::eval() called. Converting inputs to haskell-friendly...");
    std::vector<casadi::DM*> *hsArgs = new std::vector<casadi::DM*>();
    for (int k = 0; k < args.size(); k++) {
      hsArgs->push_back(new casadi::DM(args[k]));
    }
    
    std::map<std::string, casadi::GenericType> latestStats = stats();
    debug("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("HaskellCallback::eval() calling back to the haskell function...");
    std::vector<casadi::DM>* hsRet = ((hs_callback_thing)hs_fun_ptr)(hsArgs, hsStats);

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

    debug("HaskellCallback::call() return size: " << ret.size());
    debug("HaskellCallback::call() returning casadi outputs to casadi...");
    return ret;
  }
  
  // Initialize the object
  virtual void init() {
    debug("HaskellCallback::init() called...");
  }

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

}; // class HaskellCallback


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

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 (int 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);
}