// Copyright (c) 2012 by Zuse-Institute Berlin and the Technical University of Denmark.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     1. Redistributions of source code must retain the above copyright
//        notice, this list of conditions and the following disclaimer.
//     2. Redistributions in binary form must reproduce the above copyright
//        notice, this list of conditions and the following disclaimer in the
//        documentation and/or other materials provided with the distribution.
//     3. Neither the name of the copyright holders nor contributors may not
//        be used to endorse or promote products derived from this software
//        without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS NOR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "cbf-helper.h"
#include <stdlib.h>
#include <stddef.h>

CBFresponsee CBF_bucketsort(long long int maxval, long long int nnz, const long long int *val, long long int *idx)
{
  CBFresponsee res = CBF_RES_OK;
  long long int i, j, idxi, vali, k = 0;
  long long int  *bucket = NULL;
  long long int  *bucketpath  = NULL;

  bucket     = (long long int *) malloc((maxval+1) * sizeof(bucket[0]));
  bucketpath = (long long int *) malloc(nnz * sizeof(bucketpath[0]));

  if (!bucket || !bucketpath) {
    if (bucket)         free(bucket);
    if (bucketpath)     free(bucketpath);
    return CBF_RES_ERR;
  }

  if (res==CBF_RES_OK)
  {
    for (i=0; i<=maxval; ++i)
      bucket[i] = -1;

    for (i=0; i<nnz; ++i)
      bucketpath[i] = -1;
  }

  // Link elements with a common value, first pointed to by bucket[value]
  // (backwards to reverse the effect of LIFO structure and get a stable sort)
  for (i=nnz-1; i>=0 && res==CBF_RES_OK; --i) {
    idxi = idx[i];
    vali = val[idxi];

    bucketpath[idxi] = bucket[vali];
    bucket[vali] = idxi;
  }

  // Extract idx from buckets
  if ( res==CBF_RES_OK ) {
    for (i=0; i<=maxval; ++i) {
      j = bucket[i];
      while (j != -1) {
        idx[k++] = j;
        j = bucketpath[j];
      }
    }
  }

  free(bucket);
  free(bucketpath);

  return res;
}

CBFresponsee CBF_freedynamicallocations(CBFdyndata *dyndata)
{
  if (dyndata->mapstackdyncap >= 1) {
    free(dyndata->data->mapstackdim);
    free(dyndata->data->mapstackdomain);
    dyndata->data->mapstacknum = 0;
  }

  if (dyndata->varstackdyncap >= 1) {
    free(dyndata->data->varstackdim);
    free(dyndata->data->varstackdomain);
    dyndata->data->varstacknum = 0;
  }

  if (dyndata->intvardyncap >= 1) {
    free(dyndata->data->intvar);
    dyndata->data->intvarnum = 0;
  }

  if (dyndata->psdmapdyncap >= 1) {
    free(dyndata->data->psdmapdim);
    dyndata->data->psdmapnum = 0;
  }

  if (dyndata->psdvardyncap >= 1) {
    free(dyndata->data->psdvardim);
    dyndata->data->psdvarnum = 0;
  }

  if (dyndata->objfdyncap >= 1) {
    free(dyndata->data->objfsubj);
    free(dyndata->data->objfsubk);
    free(dyndata->data->objfsubl);
    free(dyndata->data->objfval);
    dyndata->data->objfnnz = 0;
  }

  if (dyndata->objadyncap >= 1) {
    free(dyndata->data->objasubj);
    free(dyndata->data->objaval);
    dyndata->data->objannz = 0;
  }

  dyndata->data->objbval = 0;

  if (dyndata->fdyncap >= 1) {
    free(dyndata->data->fsubi);
    free(dyndata->data->fsubj);
    free(dyndata->data->fsubk);
    free(dyndata->data->fsubl);
    free(dyndata->data->fval);
    dyndata->data->fnnz = 0;
  }

  if (dyndata->adyncap >= 1) {
    free(dyndata->data->asubi);
    free(dyndata->data->asubj);
    free(dyndata->data->aval);
    dyndata->data->annz = 0;
  }

  if (dyndata->bdyncap >= 1) {
    free(dyndata->data->bsubi);
    free(dyndata->data->bval);
    dyndata->data->bnnz = 0;
  }

  if (dyndata->hdyncap >= 1) {
    free(dyndata->data->hsubi);
    free(dyndata->data->hsubj);
    free(dyndata->data->hsubk);
    free(dyndata->data->hsubl);
    free(dyndata->data->hval);
    dyndata->data->hnnz = 0;
  }

  if (dyndata->ddyncap >= 1) {
    free(dyndata->data->dsubi);
    free(dyndata->data->dsubk);
    free(dyndata->data->dsubl);
    free(dyndata->data->dval);
    dyndata->data->dnnz = 0;
  }

  return CBF_RES_OK;
}

CBFresponsee CBF_map_capacitysurplus(CBFdyndata *dyndata, long long int surplus)
{
  long long int size;
  void *buf1, *buf2;

  if (dyndata->data->mapstacknum > dyndata->mapstackdyncap)
    return CBF_RES_ERR;

  size = dyndata->data->mapstacknum + surplus;

  if (size > dyndata->mapstackdyncap) {
    buf1 = realloc(dyndata->data->mapstackdim,    size*sizeof(dyndata->data->mapstackdim[0]));
    buf2 = realloc(dyndata->data->mapstackdomain, size*sizeof(dyndata->data->mapstackdomain[0]));

    if (buf1 && buf2) {
      dyndata->data->mapstackdim    = buf1;
      dyndata->data->mapstackdomain = buf2;
      dyndata->mapstackdyncap = size;
    } else {
      return CBF_RES_ERR;
    }
  }
  return CBF_RES_OK;
}

CBFresponsee CBF_map_adddomain(CBFdyndata *dyndata, CBFscalarconee domain, long long int dim)
{
  if (domain == CBF_CONE_END)
    return CBF_RES_ERR;

  if (dyndata->data->mapstacknum + 1 > dyndata->mapstackdyncap)
    return CBF_RES_ERR;

  // Always try to skip the creation of a new domains
  if (( dyndata->data->mapstacknum == 0 ) ||
      ( domain != dyndata->data->mapstackdomain[dyndata->data->mapstacknum-1] ) ||
      ( domain != CBF_CONE_FREE && domain != CBF_CONE_POS && domain != CBF_CONE_NEG && domain != CBF_CONE_ZERO))
  {
    // Create new domain
    ++dyndata->data->mapstacknum;
    dyndata->data->mapstackdim[dyndata->data->mapstacknum-1] = 0;
    dyndata->data->mapstackdomain[dyndata->data->mapstacknum-1] = domain;

  }
  // Increase dimension of current domain
  dyndata->data->mapstackdim[dyndata->data->mapstacknum-1] += dim;
  dyndata->data->mapnum += dim;

  return CBF_RES_OK;
}

CBFresponsee CBF_var_capacitysurplus(CBFdyndata *dyndata, long long int surplus)
{
  long long int size;
  void *buf1, *buf2;

  if (dyndata->data->varstacknum > dyndata->varstackdyncap)
    return CBF_RES_ERR;

  size = dyndata->data->varstacknum + surplus;

  if (size > dyndata->varstackdyncap) {
    buf1 = realloc(dyndata->data->varstackdim,    size*sizeof(dyndata->data->varstackdim[0]));
    buf2 = realloc(dyndata->data->varstackdomain, size*sizeof(dyndata->data->varstackdomain[0]));

    if (buf1 && buf2) {
      dyndata->data->varstackdim    = buf1;
      dyndata->data->varstackdomain = buf2;
      dyndata->varstackdyncap = size;
    } else {
      return CBF_RES_ERR;
    }
  }
  return CBF_RES_OK;
}

CBFresponsee CBF_var_adddomain(CBFdyndata *dyndata, CBFscalarconee domain, long long int dim)
{
  if (domain == CBF_CONE_END)
    return CBF_RES_ERR;

  if (dyndata->data->varstacknum + 1 > dyndata->varstackdyncap)
    return CBF_RES_ERR;

  // Always try to skip the creation of a new domains
  if (( dyndata->data->varstacknum == 0 ) ||
      ( domain != dyndata->data->varstackdomain[dyndata->data->varstacknum-1] ) ||
      ( domain != CBF_CONE_FREE && domain != CBF_CONE_POS && domain != CBF_CONE_NEG && domain != CBF_CONE_ZERO))
  {
    // Create new domain
    ++dyndata->data->varstacknum;
    dyndata->data->varstackdim[dyndata->data->varstacknum-1] = 0;
    dyndata->data->varstackdomain[dyndata->data->varstacknum-1] = domain;

  }
  // Increase dimension of current domain
  dyndata->data->varstackdim[dyndata->data->varstacknum-1] += dim;
  dyndata->data->varnum += dim;

  return CBF_RES_OK;
}

CBFresponsee CBF_intvar_capacitysurplus(CBFdyndata *dyndata, long long int surplus)
{
  long long int size;
  void *buf1;

  if (dyndata->data->intvarnum > dyndata->intvardyncap)
    return CBF_RES_ERR;

  size = dyndata->data->intvarnum + surplus;

  if (size > dyndata->intvardyncap) {
    buf1 = realloc(dyndata->data->intvar, size*sizeof(dyndata->data->intvar[0]));

    if (buf1) {
      dyndata->data->intvar = buf1;
      dyndata->intvardyncap = size;
    } else {
      return CBF_RES_ERR;
    }
  }
  return CBF_RES_OK;
}

CBFresponsee CBF_intvar_add(CBFdyndata *dyndata, long long int idx)
{
  if (dyndata->data->intvarnum + 1 > dyndata->intvardyncap)
    return CBF_RES_ERR;

  ++dyndata->data->intvarnum;
  dyndata->data->intvar[dyndata->data->intvarnum-1] = idx;

  return CBF_RES_OK;
}

CBFresponsee CBF_psdmap_capacitysurplus(CBFdyndata *dyndata, int surplus)
{
  long long int size;
  void *buf1;

  if (dyndata->data->psdmapnum > dyndata->psdmapdyncap)
    return CBF_RES_ERR;

  size = dyndata->data->psdmapnum + surplus;

  if (size > dyndata->psdmapdyncap) {
    buf1 = realloc(dyndata->data->psdmapdim, size*sizeof(dyndata->data->psdmapdim[0]));

    if (buf1) {
      dyndata->data->psdmapdim = buf1;
      dyndata->psdmapdyncap = size;
    } else {
      return CBF_RES_ERR;
    }
  }
  return CBF_RES_OK;
}

CBFresponsee CBF_psdmap_add(CBFdyndata *dyndata, int dim)
{
  if (dyndata->data->psdmapnum + 1 > dyndata->psdmapdyncap)
    return CBF_RES_ERR;

  ++dyndata->data->psdmapnum;
  dyndata->data->psdmapdim[dyndata->data->psdmapnum-1] = dim;

  return CBF_RES_OK;
}

CBFresponsee CBF_psdvar_capacitysurplus(CBFdyndata *dyndata, int surplus)
{
  long long int size;
  void *buf1;

  if (dyndata->data->psdvarnum > dyndata->psdvardyncap)
    return CBF_RES_ERR;

  size = dyndata->data->psdvarnum + surplus;

  if (size > dyndata->psdvardyncap) {
    buf1 = realloc(dyndata->data->psdvardim, size*sizeof(dyndata->data->psdvardim[0]));

    if (buf1) {
      dyndata->data->psdvardim = buf1;
      dyndata->psdvardyncap = size;
    } else {
      return CBF_RES_ERR;
    }
  }
  return CBF_RES_OK;
}

CBFresponsee CBF_psdvar_add(CBFdyndata *dyndata, int dim)
{
  if (dyndata->data->psdvarnum + 1 > dyndata->psdvardyncap)
    return CBF_RES_ERR;

  ++dyndata->data->psdvarnum;
  dyndata->data->psdvardim[dyndata->data->psdvarnum-1] = dim;

  return CBF_RES_OK;
}

CBFresponsee CBF_objf_capacitysurplus(CBFdyndata *dyndata, long long int surplus)
{
  long long int size;
  void *buf1, *buf2, *buf3, *buf4;

  if (dyndata->data->objfnnz > dyndata->objfdyncap)
    return CBF_RES_ERR;

  size = dyndata->data->objfnnz + surplus;

  if (size > dyndata->objfdyncap) {
    buf1 = realloc(dyndata->data->objfsubj, size*sizeof(dyndata->data->objfsubj[0]));
    buf2 = realloc(dyndata->data->objfsubk, size*sizeof(dyndata->data->objfsubk[0]));
    buf3 = realloc(dyndata->data->objfsubl, size*sizeof(dyndata->data->objfsubl[0]));
    buf4 = realloc(dyndata->data->objfval,  size*sizeof(dyndata->data->objfval[0]));

    if (buf1 && buf2 && buf3 && buf4) {
      dyndata->data->objfsubj = buf1;
      dyndata->data->objfsubk = buf2;
      dyndata->data->objfsubl = buf3;
      dyndata->data->objfval  = buf4;
      dyndata->objfdyncap = size;
    } else {
      return CBF_RES_ERR;
    }
  }
  return CBF_RES_OK;
}

CBFresponsee CBF_objf_add(CBFdyndata *dyndata, int objfsubj, int objfsubk, int objfsubl, double objfval)
{
  if (dyndata->data->objfnnz + 1 > dyndata->objfdyncap)
    return CBF_RES_ERR;

  ++dyndata->data->objfnnz;
  dyndata->data->objfsubj[dyndata->data->objfnnz-1] = objfsubj;
  dyndata->data->objfsubk[dyndata->data->objfnnz-1] = objfsubk;
  dyndata->data->objfsubl[dyndata->data->objfnnz-1] = objfsubl;
  dyndata->data->objfval [dyndata->data->objfnnz-1] = objfval;

  return CBF_RES_OK;
}

CBFresponsee CBF_obja_capacitysurplus(CBFdyndata *dyndata, long long int surplus)
{
  long long int size;
  void *buf1, *buf2;

  if (dyndata->data->objannz > dyndata->objadyncap)
    return CBF_RES_ERR;

  size = dyndata->data->objannz + surplus;

  if (size > dyndata->objadyncap) {
    buf1 = realloc(dyndata->data->objasubj, size*sizeof(dyndata->data->objasubj[0]));
    buf2 = realloc(dyndata->data->objaval,  size*sizeof(dyndata->data->objaval[0]));

    if (buf1 && buf2) {
      dyndata->data->objasubj = buf1;
      dyndata->data->objaval  = buf2;
      dyndata->objadyncap = size;
    } else {
      return CBF_RES_ERR;
    }
  }
  return CBF_RES_OK;
}

CBFresponsee CBF_obja_add(CBFdyndata *dyndata, long long int objasubj, double objaval)
{
  if (dyndata->data->objannz + 1 > dyndata->objadyncap)
    return CBF_RES_ERR;

  ++dyndata->data->objannz;
  dyndata->data->objasubj[dyndata->data->objannz-1] = objasubj;
  dyndata->data->objaval [dyndata->data->objannz-1] = objaval;

  return CBF_RES_OK;
}

CBFresponsee CBF_objb_set(CBFdyndata *dyndata, double objbval)
{
  dyndata->data->objbval = objbval;
  return CBF_RES_OK;
}

CBFresponsee CBF_f_capacitysurplus(CBFdyndata *dyndata, long long int surplus)
{
  long long int size;
  void *buf1, *buf2, *buf3, *buf4, *buf5;

  if (dyndata->data->fnnz > dyndata->fdyncap)
    return CBF_RES_ERR;

  size = dyndata->data->fnnz + surplus;

  if (size > dyndata->fdyncap) {
    buf1 = realloc(dyndata->data->fsubi, size*sizeof(dyndata->data->fsubi[0]));
    buf2 = realloc(dyndata->data->fsubj, size*sizeof(dyndata->data->fsubj[0]));
    buf3 = realloc(dyndata->data->fsubk, size*sizeof(dyndata->data->fsubk[0]));
    buf4 = realloc(dyndata->data->fsubl, size*sizeof(dyndata->data->fsubl[0]));
    buf5 = realloc(dyndata->data->fval,  size*sizeof(dyndata->data->fval[0]));

    if (buf1 && buf2 && buf3 && buf4 && buf5) {
      dyndata->data->fsubi = buf1;
      dyndata->data->fsubj = buf2;
      dyndata->data->fsubk = buf3;
      dyndata->data->fsubl = buf4;
      dyndata->data->fval  = buf5;
      dyndata->fdyncap = size;
    } else {
      return CBF_RES_ERR;
    }
  }
  return CBF_RES_OK;
}

CBFresponsee CBF_f_add(CBFdyndata *dyndata, long long int fsubi, int fsubj, int fsubk, int fsubl, double fval)
{
  if (dyndata->data->fnnz + 1 > dyndata->fdyncap)
    return CBF_RES_ERR;

  ++dyndata->data->fnnz;
  dyndata->data->fsubi[dyndata->data->fnnz-1] = fsubi;
  dyndata->data->fsubj[dyndata->data->fnnz-1] = fsubj;
  dyndata->data->fsubk[dyndata->data->fnnz-1] = fsubk;
  dyndata->data->fsubl[dyndata->data->fnnz-1] = fsubl;
  dyndata->data->fval [dyndata->data->fnnz-1] = fval;

  return CBF_RES_OK;
}

CBFresponsee CBF_a_capacitysurplus(CBFdyndata *dyndata, long long int surplus)
{
  long long int size;
  void *buf1, *buf2, *buf3;

  if (dyndata->data->annz > dyndata->adyncap)
    return CBF_RES_ERR;

  size = dyndata->data->annz + surplus;

  if (size > dyndata->adyncap) {
    buf1 = realloc(dyndata->data->asubi, size*sizeof(dyndata->data->asubi[0]));
    buf2 = realloc(dyndata->data->asubj, size*sizeof(dyndata->data->asubj[0]));
    buf3 = realloc(dyndata->data->aval,  size*sizeof(dyndata->data->aval[0]));

    if (buf1 && buf2 && buf3) {
      dyndata->data->asubi = buf1;
      dyndata->data->asubj = buf2;
      dyndata->data->aval  = buf3;
      dyndata->adyncap = size;
    } else {
      return CBF_RES_ERR;
    }
  }
  return CBF_RES_OK;
}

CBFresponsee CBF_a_add(CBFdyndata *dyndata, long long int asubi, long long int asubj, double aval)
{
  if (dyndata->data->annz + 1 > dyndata->adyncap)
    return CBF_RES_ERR;

  ++dyndata->data->annz;
  dyndata->data->asubi[dyndata->data->annz-1] = asubi;
  dyndata->data->asubj[dyndata->data->annz-1] = asubj;
  dyndata->data->aval [dyndata->data->annz-1] = aval;

  return CBF_RES_OK;
}

CBFresponsee CBF_b_capacitysurplus(CBFdyndata *dyndata, long long int surplus)
{
  long long int size;
  void *buf1, *buf2;

  if (dyndata->data->bnnz > dyndata->bdyncap)
    return CBF_RES_ERR;

  size = dyndata->data->bnnz + surplus;

  if (size > dyndata->bdyncap) {
    buf1 = realloc(dyndata->data->bsubi, size*sizeof(dyndata->data->bsubi[0]));
    buf2 = realloc(dyndata->data->bval,  size*sizeof(dyndata->data->bval[0]));

    if (buf1 && buf2) {
      dyndata->data->bsubi = buf1;
      dyndata->data->bval  = buf2;
      dyndata->bdyncap = size;
    } else {
      return CBF_RES_ERR;
    }
  }
  return CBF_RES_OK;
}

CBFresponsee CBF_b_add(CBFdyndata *dyndata, long long int bsubi, double bval)
{
  if (dyndata->data->bnnz + 1 > dyndata->bdyncap)
    return CBF_RES_ERR;

  ++dyndata->data->bnnz;
  dyndata->data->bsubi[dyndata->data->bnnz-1] = bsubi;
  dyndata->data->bval [dyndata->data->bnnz-1] = bval;

  return CBF_RES_OK;
}

CBFresponsee CBF_h_capacitysurplus(CBFdyndata *dyndata, long long int surplus)
{
  long long int size;
  void *buf1, *buf2, *buf3, *buf4, *buf5;

  if (dyndata->data->hnnz > dyndata->hdyncap)
    return CBF_RES_ERR;

  size = dyndata->data->hnnz + surplus;

  if (size > dyndata->hdyncap) {
    buf1 = realloc(dyndata->data->hsubi, size*sizeof(dyndata->data->hsubi[0]));
    buf2 = realloc(dyndata->data->hsubj, size*sizeof(dyndata->data->hsubj[0]));
    buf3 = realloc(dyndata->data->hsubk, size*sizeof(dyndata->data->hsubk[0]));
    buf4 = realloc(dyndata->data->hsubl, size*sizeof(dyndata->data->hsubl[0]));
    buf5 = realloc(dyndata->data->hval,  size*sizeof(dyndata->data->hval[0]));

    if (buf1 && buf2 && buf3 && buf4 && buf5) {
      dyndata->data->hsubi = buf1;
      dyndata->data->hsubj = buf2;
      dyndata->data->hsubk = buf3;
      dyndata->data->hsubl = buf4;
      dyndata->data->hval  = buf5;
      dyndata->hdyncap = size;
    } else {
      return CBF_RES_ERR;
    }
  }
  return CBF_RES_OK;
}

CBFresponsee CBF_h_add(CBFdyndata *dyndata, int hsubi, long long int hsubj, int hsubk, int hsubl, double hval)
{
  if (dyndata->data->hnnz + 1 > dyndata->hdyncap)
    return CBF_RES_ERR;

  ++dyndata->data->hnnz;
  dyndata->data->hsubi[dyndata->data->hnnz-1] = hsubi;
  dyndata->data->hsubj[dyndata->data->hnnz-1] = hsubj;
  dyndata->data->hsubk[dyndata->data->hnnz-1] = hsubk;
  dyndata->data->hsubl[dyndata->data->hnnz-1] = hsubl;
  dyndata->data->hval [dyndata->data->hnnz-1] = hval;

  return CBF_RES_OK;
}

CBFresponsee CBF_d_capacitysurplus(CBFdyndata *dyndata, long long int surplus)
{
  long long int size;
  void *buf1, *buf2, *buf3, *buf4;

  if (dyndata->data->dnnz > dyndata->ddyncap)
    return CBF_RES_ERR;

  size = dyndata->data->dnnz + surplus;

  if (size > dyndata->ddyncap) {
    buf1 = realloc(dyndata->data->dsubi, size*sizeof(dyndata->data->dsubi[0]));
    buf2 = realloc(dyndata->data->dsubk, size*sizeof(dyndata->data->dsubk[0]));
    buf3 = realloc(dyndata->data->dsubl, size*sizeof(dyndata->data->dsubl[0]));
    buf4 = realloc(dyndata->data->dval,  size*sizeof(dyndata->data->dval[0]));

    if (buf1 && buf2 && buf3 && buf4) {
      dyndata->data->dsubi = buf1;
      dyndata->data->dsubk = buf2;
      dyndata->data->dsubl = buf3;
      dyndata->data->dval  = buf4;
      dyndata->ddyncap = size;
    } else {
      return CBF_RES_ERR;
    }
  }
  return CBF_RES_OK;
}

CBFresponsee CBF_d_add(CBFdyndata *dyndata, int dsubi, int dsubk, int dsubl, double dval)
{
  if (dyndata->data->dnnz + 1 > dyndata->ddyncap)
    return CBF_RES_ERR;

  ++dyndata->data->dnnz;
  dyndata->data->dsubi[dyndata->data->dnnz-1] = dsubi;
  dyndata->data->dsubk[dyndata->data->dnnz-1] = dsubk;
  dyndata->data->dsubl[dyndata->data->dnnz-1] = dsubl;
  dyndata->data->dval [dyndata->data->dnnz-1] = dval;

  return CBF_RES_OK;
}

CBFresponsee CBF_varbound_capacitysurplus(CBFdyndata *dyndata, long long int surplus)
{
  CBFresponsee res = CBF_RES_OK;
  res = CBF_map_capacitysurplus(dyndata, surplus);

  if ( res==CBF_RES_OK )
    CBF_a_capacitysurplus(dyndata, surplus);

  return res;
}

CBFresponsee CBF_varbound_addlower(CBFdyndata *dyndata, long long int idx, double lower)
{
  // x[i] - lower >= 0
  CBFresponsee res = CBF_RES_OK;
  res = CBF_map_adddomain(dyndata, CBF_CONE_POS, 1);

  if ( res==CBF_RES_OK )
    if ( lower != 0.0 )
      res = CBF_b_add(dyndata, dyndata->data->mapnum-1, -lower);

  if ( res==CBF_RES_OK )
    res = CBF_a_add(dyndata, dyndata->data->mapnum-1, idx, 1.0);

  return res;
}

CBFresponsee CBF_varbound_addupper(CBFdyndata *dyndata, long long int idx, double upper)
{
  // x[i] - upper <= 0
  CBFresponsee res = CBF_RES_OK;
  res = CBF_map_adddomain(dyndata, CBF_CONE_NEG, 1);

  if ( res==CBF_RES_OK )
    if ( upper != 0.0 )
      res = CBF_b_add(dyndata, dyndata->data->mapnum-1, -upper);

  if ( res==CBF_RES_OK )
    res = CBF_a_add(dyndata, dyndata->data->mapnum-1, idx, 1.0);

  return res;
}

CBFresponsee CBF_varbound_addfix(CBFdyndata *dyndata, long long int idx, double fix)
{
  // x[i] - fix == 0
  CBFresponsee res = CBF_RES_OK;
  res = CBF_map_adddomain(dyndata, CBF_CONE_ZERO, 1);

  if ( res==CBF_RES_OK )
    if ( fix != 0.0 )
      res = CBF_b_add(dyndata, dyndata->data->mapnum-1, -fix);

  if ( res==CBF_RES_OK )
    res = CBF_a_add(dyndata, dyndata->data->mapnum-1, idx, 1.0);

  return res;
}
