extern int BackendDAEEXT_setAssignment(int lenass1, int lenass2, modelica_metatype ass1, modelica_metatype ass2)
{
  int nelts=0;
  int i=0;

  nelts = MMC_HDRSLOTS(MMC_GETHDR(ass1));
  if (nelts > 0) {
    n = lenass1;
    if(match) {
      free(match);
    }
    match = (int*) malloc(n * sizeof(int));
    for(i=0; i<n; ++i) {
      match[i] = MMC_UNTAGFIXNUM(MMC_STRUCTDATA(ass1)[i])-1;
      if (match[i]<0) match[i] = -1;
    }
  }
  nelts = MMC_HDRSLOTS(MMC_GETHDR(ass2));
  if (nelts > 0) {
    m = lenass2;
    if(row_match) {
      free(row_match);
    }
    row_match = (int*) malloc(m * sizeof(int));
    for(i=0; i<m; ++i) {
      row_match[i] = MMC_UNTAGFIXNUM(MMC_STRUCTDATA(ass2)[i])-1;
      if (row_match[i]<0) row_match[i] = -1;
    }
  }
  return 1;
}
extern void BackendDAEEXT_getAssignment(modelica_metatype ass1, modelica_metatype ass2)
{
  int i=0;
  long len1 = MMC_HDRSLOTS(MMC_GETHDR(ass1));
  long len2 = MMC_HDRSLOTS(MMC_GETHDR(ass2));
  if (n > len1 || m > len2) {
    char nstr[64],mstr[64],len1str[64],len2str[64];
    const char *tokens[4] = {len2str,mstr,len1str,nstr};
    snprintf(nstr,64,"%ld", (long) n);
    snprintf(mstr,64,"%ld", (long) m);
    snprintf(len1str,64,"%ld", (long) len1);
    snprintf(len2str,64,"%ld", (long) len2);
    c_add_message(NULL,-1,ErrorType_symbolic,ErrorLevel_internal,"BackendDAEEXT.getAssignment failed because n=%s>arrayLength(ass1)=%s or m=%s>arrayLength(ass2)=%s",tokens,4);
    MMC_THROW();
  }
  if (match != NULL) {
    for(i=0; i<n; ++i) {
      if (match[i] >= 0)
        MMC_STRUCTDATA(ass1)[i] = mmc_mk_icon(match[i]+1);
      else
        MMC_STRUCTDATA(ass1)[i] = mmc_mk_icon(-1);
    }
  }
  if (row_match != NULL) {
    for(i=0; i<m; ++i) {
      if (row_match[i] >= 0)
        MMC_STRUCTDATA(ass2)[i] = mmc_mk_icon(row_match[i]+1);
      else
        MMC_STRUCTDATA(ass2)[i] = mmc_mk_icon(-1);
    }
  }
}
modelica_metatype boxptr_stringUpdateStringChar(threadData_t *threadData,metamodelica_string str, metamodelica_string c, modelica_metatype iix)
{
  int ix = MMC_UNTAGFIXNUM(iix);
  int length = 0;
  unsigned header = MMC_GETHDR(str);
  unsigned nwords = MMC_HDRSLOTS(header) + 1;
  struct mmc_string *p = NULL;
  void *res = NULL;

  MMC_CHECK_STRING(str);
  MMC_CHECK_STRING(c);
  /* fprintf(stderr, "stringUpdateStringChar(%s,%s,%ld)\n", MMC_STRINGDATA(str),MMC_STRINGDATA(c),ix); */

  if (ix < 1 || MMC_STRLEN(c) != 1)
    MMC_THROW_INTERNAL();
  length = MMC_STRLEN(str);
  if (ix > length)
    MMC_THROW_INTERNAL();
  p = (struct mmc_string *) mmc_alloc_words_atomic(nwords);
  p->header = header;
  memcpy(p->data, MMC_STRINGDATA(str), length+1 /* include NULL */);
  p->data[ix-1] = MMC_STRINGDATA(c)[0];
  res = MMC_TAGPTR(p);
  MMC_CHECK_STRING(res);
  return res;
}
metamodelica_string_const stringAppend(metamodelica_string_const s1, metamodelica_string_const s2)
{
  unsigned len1 = 0, len2 = 0, nbytes = 0, header = 0, nwords = 0;
  void *res = NULL;
  struct mmc_string *p = NULL;
  MMC_CHECK_STRING(s1);
  MMC_CHECK_STRING(s2);

  /* fprintf(stderr, "stringAppend([%p] %s, [%p] %s)->\n", s1, anyString(s1), s2, anyString(s2)); fflush(NULL); */
  len1 = MMC_STRLEN(s1);
  len2 = MMC_STRLEN(s2);
  nbytes = len1+len2;
  header = MMC_STRINGHDR(nbytes);
  nwords = MMC_HDRSLOTS(header) + 1;
  p = (struct mmc_string *) mmc_alloc_words_atomic(nwords);
  /* fprintf(stderr, "at address %p\n", MMC_TAGPTR(p)); fflush(NULL); */
  p->header = header;

  memcpy(p->data, MMC_STRINGDATA(s1), len1);
  memcpy(p->data + len1, MMC_STRINGDATA(s2), len2 + 1);
  res = MMC_TAGPTR(p);
  MMC_CHECK_STRING(res);
  /* fprintf(stderr, "-> %s\n", anyString(res)); fflush(NULL); */
  return res;
}
extern void BackendDAEEXT_setIncidenceMatrix(modelica_integer nvars, modelica_integer neqns, modelica_integer nz, modelica_metatype incidencematrix)
{
  int i=0;
  long int i1;
  int j=0;
  modelica_integer nelts = MMC_HDRSLOTS(MMC_GETHDR(incidencematrix));

  if (col_ptrs) free(col_ptrs);
  col_ptrs = (int*) malloc((neqns+1) * sizeof(int));
  col_ptrs[neqns]=nz;
  if (col_ids) free(col_ids);
  col_ids = (int*) malloc(nz * sizeof(int));

  for(i=0; i<neqns; ++i) {
    modelica_metatype ie = MMC_STRUCTDATA(incidencematrix)[i];
    col_ptrs[i] = j;
    while(MMC_GETHDR(ie) == MMC_CONSHDR) {
      i1 = MMC_UNTAGFIXNUM(MMC_CAR(ie));
      if (i1>0) {
        col_ids[j++] = i1-1;
      }
      ie = MMC_CDR(ie);
    }
  }
}
modelica_metatype arrayAppend(modelica_metatype arr1, modelica_metatype arr2)
{
  int nelts1 = MMC_HDRSLOTS(MMC_GETHDR(arr1));
  int nelts2 = MMC_HDRSLOTS(MMC_GETHDR(arr2));
  void* res = (struct mmc_struct*)mmc_mk_box_no_assign(nelts1 + nelts2, MMC_ARRAY_TAG);
  void **arr1p = MMC_STRUCTDATA(arr1);
  void **arr2p = MMC_STRUCTDATA(arr2);
  void **resp = MMC_STRUCTDATA(res);
  int i;
  for (i=0; i<nelts1; ++i) {
    resp[i] = arr1p[i];
  }
  for (i=0; i<nelts2; ++i) {
    resp[i+nelts1] = arr2p[i];
  }
  return res;
}
modelica_metatype arrayCopy(modelica_metatype arr)
{
  int nelts = MMC_HDRSLOTS(MMC_GETHDR(arr));
  void* res = (struct mmc_struct*)mmc_mk_box_no_assign(nelts, MMC_ARRAY_TAG);
  void **arrp = MMC_STRUCTDATA(arr);
  void **resp = MMC_STRUCTDATA(res);
  memcpy(resp, arrp, sizeof(modelica_metatype)*nelts);
  return res;
}
extern void* HpcOmSchedulerExt_scheduleMetis(modelica_metatype xadjIn, modelica_metatype adjncyIn, modelica_metatype vwgtIn, modelica_metatype adjwgtIn, int npartsIn)
{
#if defined(_MSC_VER)
  HPC_OM_VS();
#else
  int xadjNelts = (int)MMC_HDRSLOTS(MMC_GETHDR(xadjIn)); //number of elements in xadj-array
  int adjncyNelts = (int)MMC_HDRSLOTS(MMC_GETHDR(adjncyIn)); //number of elements in adjncy-array
  int vwgtNelts = (int)MMC_HDRSLOTS(MMC_GETHDR(vwgtIn)); //number of elements in vwgt-array
  int adjwgtNelts = (int)MMC_HDRSLOTS(MMC_GETHDR(adjwgtIn)); //number of elements in adjwgt-array
  int nparts = npartsIn;

  int* xadj = (int *) malloc(xadjNelts*sizeof(int));
  int* adjncy = (int *) malloc(adjncyNelts*sizeof(int));
  int* vwgt = (int *) malloc(vwgtNelts*sizeof(int));
  int* adjwgt = (int *) malloc(adjwgtNelts*sizeof(int));

  //setup xadj
  for(int i=0; i<xadjNelts; i++) {
    int xadjElem = MMC_UNTAGFIXNUM(MMC_STRUCTDATA(xadjIn)[i]);
    //std::cerr << "xadjElem: " << xadjElem << std::endl;
    xadj[i] = xadjElem;
  }
  //setup adjncy
  for(int i=0; i<adjncyNelts; i++) {
    int adjncyElem = MMC_UNTAGFIXNUM(MMC_STRUCTDATA(adjncyIn)[i]);
    //std::cerr << "adjncyElem: " << adjncyElem << std::endl;
    adjncy[i] = adjncyElem;
  }
  //setup vwgt
  for(int i=0; i<vwgtNelts; i++) {
    int vwgtElem = MMC_UNTAGFIXNUM(MMC_STRUCTDATA(vwgtIn)[i]);
    //std::cerr << "vwgtElem: " << vwgtElem << std::endl;
    vwgt[i] = vwgtElem;
  }
  //setup adjwgt
  for(int i=0; i<adjwgtNelts; i++) {
    int adjwgtElem = MMC_UNTAGFIXNUM(MMC_STRUCTDATA(adjwgtIn)[i]);
    //std::cerr << "adjwgtElem: " << adjwgtElem << std::endl;
    adjwgt[i] = adjwgtElem;
  }

  return HpcOmSchedulerExtImpl__scheduleMetis(xadj, adjncy, vwgt, adjwgt, xadjNelts, adjncyNelts, nparts);
}
modelica_metatype arrayList(modelica_metatype arr)
{
  modelica_metatype result;
  int nelts = MMC_HDRSLOTS(MMC_GETHDR(arr))-1;
  void **vecp = MMC_STRUCTDATA(arr);
  void *res = mmc_mk_nil();
  for(; nelts >= 0; --nelts) {
    res = mmc_mk_cons(vecp[nelts],res);
  }
  return res;
}
extern void* HpcOmSchedulerExt_schedulehMetis(modelica_metatype xadjIn, modelica_metatype adjncyIn, modelica_metatype vwgtIn, modelica_metatype adjwgtIn, int npartsIn)
{

  int vwgtsNelts = (int)MMC_HDRSLOTS(MMC_GETHDR(xadjIn)); //number of elements in xadj-array
  int eptrNelts = (int)MMC_HDRSLOTS(MMC_GETHDR(adjncyIn)); //number of elements in adjncy-array
  int eintNelts = (int)MMC_HDRSLOTS(MMC_GETHDR(vwgtIn)); //number of elements in vwgt-array
  int hewgtsNelts = (int)MMC_HDRSLOTS(MMC_GETHDR(adjwgtIn)); //number of elements in adjwgt-array
  int nparts = npartsIn;

  int* vwgts = (int *) malloc(vwgtsNelts*sizeof(int));
  int* eptr = (int *) malloc(eptrNelts*sizeof(int));
  int* eint = (int *) malloc(eintNelts*sizeof(int));
  int* hewgts = (int *) malloc(hewgtsNelts*sizeof(int));

  //setup xadj
  for(int i=0; i<vwgtsNelts; i++) {
    int xadjElem = MMC_UNTAGFIXNUM(MMC_STRUCTDATA(xadjIn)[i]);
    std::cerr << "vwgtsElem: " << xadjElem << std::endl;
    vwgts[i] = xadjElem;
  }
  //setup adjncy
  for(int i=0; i<eptrNelts; i++) {
    int adjncyElem = MMC_UNTAGFIXNUM(MMC_STRUCTDATA(adjncyIn)[i]);
    std::cerr << "eptrElem: " << adjncyElem << std::endl;
    eptr[i] = adjncyElem;
  }
  //setup vwgt
  for(int i=0; i<eintNelts; i++) {
    int vwgtElem = MMC_UNTAGFIXNUM(MMC_STRUCTDATA(vwgtIn)[i]);
    std::cerr << "eintElem: " << vwgtElem << std::endl;
    eint[i] = vwgtElem;
  }
  //setup adjwgt
  for(int i=0; i<hewgtsNelts; i++) {
    int adjwgtElem = MMC_UNTAGFIXNUM(MMC_STRUCTDATA(adjwgtIn)[i]);
    std::cerr << "adjwgtElem: " << adjwgtElem << std::endl;
    hewgts[i] = adjwgtElem;
  }
  return HpcOmSchedulerExtImpl__scheduleMetis(vwgts, eptr, eint, hewgts, vwgtsNelts, eptrNelts, nparts);
#endif
}
modelica_metatype arrayCopy(modelica_metatype arr)
{
  int nelts = MMC_HDRSLOTS(MMC_GETHDR(arr));
  void* res = (struct mmc_struct*)mmc_mk_box_no_assign(nelts, MMC_ARRAY_TAG);
  void **arrp = MMC_STRUCTDATA(arr);
  void **resp = MMC_STRUCTDATA(res);
  int i = 0;
  for(i=0; i<nelts; i++) {
    resp[i] = arrp[i];
  }
  return res;
}
metamodelica_string stringAppendList(modelica_metatype lst)
{
  /* fprintf(stderr, "stringAppendList(%s)\n", anyString(lst)); */
  modelica_integer lstLen = 0, len = 0;
  unsigned nbytes = 0, header = 0, nwords = 0;
  modelica_metatype car = NULL, lstHead = NULL, lstTmp = NULL;
  char *tmp = NULL;
  struct mmc_string *res = NULL;
  void *p = NULL;

  lstLen = 0;
  nbytes = 0;
  lstHead = lst;
  lstTmp = lst;
  while (!listEmpty(lstTmp)) {
    MMC_CHECK_STRING(MMC_CAR(lstTmp));
    nbytes += MMC_STRLEN(MMC_CAR(lstTmp));
    /* fprintf(stderr, "stringAppendList: Has success reading input %d: %s\n", lstLen, MMC_STRINGDATA(MMC_CAR(lst))); */
    lstTmp = MMC_CDR(lstTmp);
    lstLen++;
  }
  if (nbytes == 0) return mmc_emptystring;
  if (lstLen == 1) return MMC_CAR(lstHead);

  header = MMC_STRINGHDR(nbytes);
  nwords = MMC_HDRSLOTS(header) + 1;
  res = (struct mmc_string *) mmc_alloc_words_atomic(nwords);
  res->header = header;
  tmp = (char*) res->data;
  nbytes = 0;
  lstTmp = lstHead;
  while (!listEmpty(lstTmp)) {
    car = MMC_CAR(lstTmp);
    len = MMC_STRLEN(car);
    /* fprintf(stderr, "stringAppendList: %s %d %d\n", MMC_STRINGDATA(car), len, strlen(MMC_STRINGDATA(car))); */
    /* Might be useful to check this when debugging. String literals are often done wrong :) */
    MMC_DEBUG_ASSERT(len == strlen(MMC_STRINGDATA(car)));
    memcpy(tmp+nbytes,MMC_STRINGDATA(car),len);
    nbytes += len;
    lstTmp = MMC_CDR(lstTmp);
  }
  tmp[nbytes] = '\0';
  /* fprintf(stderr, "stringAppendList(%s)=>%s\n", anyString(lstHead), anyString(MMC_TAGPTR(res))); */
  p = MMC_TAGPTR(res);
  MMC_CHECK_STRING(p);
  return p;
}
modelica_metatype boxptr_substring(threadData_t *threadData, metamodelica_string_const str, modelica_metatype boxstart, modelica_metatype boxstop)
{
  unsigned header = 0, nwords;
  long start = MMC_UNTAGFIXNUM(boxstart) - 1;
  long stop = MMC_UNTAGFIXNUM(boxstop) - 1;
  long totalLen = MMC_STRLEN(str), len = stop-start+1;
  struct mmc_string *res;
  char *tmp;
  modelica_metatype p;
  /* Bad indexes */
  if (start < 0 || start >= totalLen || stop < start || stop >= totalLen) {
    MMC_THROW_INTERNAL();
  }
  header = MMC_STRINGHDR(len);
  nwords = MMC_HDRSLOTS(header) + 1;
  res = (struct mmc_string *) mmc_alloc_words_atomic(nwords);
  res->header = header;
  tmp = (char*) res->data;
  memcpy(tmp, MMC_STRINGDATA(str) + start, len);
  tmp[len] = '\0';
  p = MMC_TAGPTR(res);
  MMC_CHECK_STRING(p);
  return p;
}