 
 
 __device__ __host__
-void replace_input_poly_cons_in_lexpr(expr_t** expr_ptr, double* input_inf, double* input_sup, expr_t** input_lexpr, expr_t** input_uexpr)
-{
-    expr_t* expr = *expr_ptr;
-
-    double tmp1, tmp2;
-    expr_t* res;
-
-    size_t k;
-
-    if(expr->type == DENSE)
-    {
-        k = 0;
-    }
-    else
-    {
-        k = expr->dim[0];
-    }
-
-    expr_t* mul_expr = nullptr;
-
-    if(expr->sup_coeff[0] < 0)
-    {
-        mul_expr = input_uexpr[k];
-    }
-    else if(expr->inf_coeff[0] < 0)
-    {
-        mul_expr = input_lexpr[k];
-    }
-
-    if(mul_expr != nullptr)
-    {
-        if(mul_expr->size == 0)
-        {
-            res = multiply_cst_expr(mul_expr, expr->inf_coeff[0], expr->sup_coeff[0]);
+void replace_input_poly_cons_in_lexpr(expr_t** expr_array, double* input_inf, double* input_sup, expr_t** input_lexpr, expr_t** input_uexpr, const size_t size)
+{
+    for(size_t n = 0; n < size; n++)
+    {
+        expr_t* expr = expr_array[n];
+
+        double tmp1, tmp2;
+        expr_t* res;
+
+        size_t k;
+
+        if(expr->type == DENSE)
+        {
+            k = 0;
         }
         else
         {
-            res = multiply_expr(mul_expr, expr->inf_coeff[0], expr->sup_coeff[0]);
-        }
-    }
-
-    else
-    {
-        elina_double_interval_mul(&tmp1, &tmp2, expr->inf_coeff[0], expr->sup_coeff[0], input_inf[k], input_sup[k]);
-        res = create_cst_expr(tmp1, -tmp1);
-    }
-
-    for(size_t i = 1; i < expr->size; i++)
-    {
+            k = expr->dim[0];
+        }
+
+        expr_t* mul_expr = nullptr;
+
+        if(expr->sup_coeff[0] < 0)
+        {
+            mul_expr = input_uexpr[k];
+        }
+        else if(expr->inf_coeff[0] < 0)
+        {
+            mul_expr = input_lexpr[k];
+        }
+
+        if(mul_expr != nullptr)
+        {
+            if(mul_expr->size == 0)
+            {
+                res = multiply_cst_expr(mul_expr, expr->inf_coeff[0], expr->sup_coeff[0]);
+            }
+            else
+            {
+                res = multiply_expr(mul_expr, expr->inf_coeff[0], expr->sup_coeff[0]);
+            }
+        }
+
+        else
+        {
+            elina_double_interval_mul(&tmp1, &tmp2, expr->inf_coeff[0], expr->sup_coeff[0], input_inf[k], input_sup[k]);
+            res = create_cst_expr(tmp1, -tmp1);
+        }
+
+        for(size_t i = 1; i < expr->size; i++)
+        {
+            if(expr->type == DENSE)
+            {
+                k = i;
+            }
+            else
+            {
+                k = expr->dim[i];
+            }
+
+            expr_t* mul_expr = nullptr;
+            expr_t* sum_expr = nullptr;
+
+            if(expr->sup_coeff[i] < 0)
+            {
+                mul_expr = input_uexpr[k];
+            }
+            else if(expr->inf_coeff[i] < 0)
+            {
+                mul_expr = input_lexpr[k];
+            }
+
+            if(mul_expr != nullptr)
+            {
+                if(mul_expr->size == 0)
+                {
+                    sum_expr = multiply_cst_expr(mul_expr, expr->inf_coeff[i], expr->sup_coeff[i]);
+                    add_cst_expr(res, sum_expr);
+                }
+                else if((expr->inf_coeff[i] != 0) && (expr->sup_coeff[i] != 0))
+                {
+                    sum_expr = multiply_expr(mul_expr, expr->inf_coeff[i], expr->sup_coeff[i]);
+                    add_expr(res, sum_expr);
+                }
+                    //free_expr(mul_expr);
+                if(sum_expr != nullptr)
+                {
+                    free_expr(sum_expr);
+                }
+            }
+            else
+            {
+                elina_double_interval_mul(&tmp1, &tmp2, expr->inf_coeff[i], expr->sup_coeff[i], input_inf[k], input_sup[k]);
+                res->inf_cst = res->inf_cst + tmp1;
+                res->sup_cst = res->sup_cst - tmp1;
+            }
+        }
+
+        res->inf_cst = res->inf_cst + expr->inf_cst;
+        res->sup_cst = res->sup_cst + expr->sup_cst;
+
+        free(expr);
+        expr_array[n] = res;
+    }
+}
+
+
+__device__ __host__
+void replace_input_poly_cons_in_uexpr(expr_t** expr_array, double* input_inf, double* input_sup, expr_t** input_lexpr, expr_t** input_uexpr, const size_t size)
+{
+    for(size_t n = 0; n < size; n++)
+    {
+        expr_t* expr = expr_array[n];
+
+        double tmp1, tmp2;
+        expr_t* res;
+
+        size_t k;
+
         if(expr->type == DENSE)
         {
-            k = i;
+            k = 0;
         }
         else
         {
-            k = expr->dim[i];
-        }
-
-        expr_t* mul_expr = nullptr;
-        expr_t* sum_expr = nullptr;
-
-        if(expr->sup_coeff[i] < 0)
+            k = expr->dim[0];
+        }
+
+        expr_t * mul_expr = nullptr;
+
+        if(expr->sup_coeff[0] < 0)
+        {
+            mul_expr = input_lexpr[k];
+        }
+        else if(expr->inf_coeff[0] < 0)
         {
             mul_expr = input_uexpr[k];
         }
-        else if(expr->inf_coeff[i] < 0)
-        {
-            mul_expr = input_lexpr[k];
-        }
 
         if(mul_expr != nullptr)
         {
             if(mul_expr->size == 0)
             {
-                sum_expr = multiply_cst_expr(mul_expr, expr->inf_coeff[i], expr->sup_coeff[i]);
-                add_cst_expr(res, sum_expr);
-            }
-            else if((expr->inf_coeff[i] != 0) && (expr->sup_coeff[i] != 0))
-            {
-                sum_expr = multiply_expr(mul_expr, expr->inf_coeff[i], expr->sup_coeff[i]);
-                add_expr(res, sum_expr);
-            }
-                //free_expr(mul_expr);
-            if(sum_expr != nullptr)
-            {
-                free_expr(sum_expr);
+                res = multiply_cst_expr(mul_expr, expr->inf_coeff[0], expr->sup_coeff[0]);
+            }
+            else
+            {
+                res = multiply_expr(mul_expr, expr->inf_coeff[0], expr->sup_coeff[0]);
             }
         }
         else
         {
+            elina_double_interval_mul(&tmp1, &tmp2, expr->inf_coeff[0], expr->sup_coeff[0], input_inf[k], input_sup[k]);
+            res = create_cst_expr(-tmp2, tmp2);
+        }
+                    //printf("finish\n");
+            //fflush(stdout);
+        for(size_t i = 1; i < expr->size; i++)
+        {
+            if(expr->type == DENSE)
+            {
+                k = i;
+            }
+            else
+            {
+                k = expr->dim[i];
+            }
+
+            expr_t* mul_expr = nullptr;
+            expr_t* sum_expr = nullptr;
+
+            if(expr->sup_coeff[i] < 0)
+            {
+                mul_expr = input_lexpr[k];
+            }
+            else if(expr->inf_coeff[i] < 0)
+            {
+                mul_expr = input_uexpr[k];
+            }
+
+            if(mul_expr != nullptr)
+            {
+                if(mul_expr->size == 0)
+                {
+                    sum_expr = multiply_cst_expr(mul_expr, expr->inf_coeff[i], expr->sup_coeff[i]);
+                    add_cst_expr(res, sum_expr);
+                }
+                else if((expr->inf_coeff[i] != 0) && (expr->sup_coeff[i] != 0))
+                {
+                    sum_expr = multiply_expr(mul_expr, expr->inf_coeff[i], expr->sup_coeff[i]);
+                    add_expr(res, sum_expr);
+                }
+                    //free_expr(mul_expr);
+                if(sum_expr != nullptr)
+                {
+                    free_expr(sum_expr);
+                }
+            }
+            else
+            {
+                elina_double_interval_mul(&tmp1, &tmp2, expr->inf_coeff[i], expr->sup_coeff[i], input_inf[k], input_sup[k]);
+                res->inf_cst = res->inf_cst - tmp2;
+                res->sup_cst = res->sup_cst + tmp2;
+            }
+        }
+
+        res->inf_cst = res->inf_cst + expr->inf_cst;
+        res->sup_cst = res->sup_cst + expr->sup_cst;
+
+        free(expr);
+        expr_array[n] = res;
+    }
+}
+
+
+__device__ __host__
+void compute_lb_from_expr(double* lb_array, expr_t** expr_array, double* input_inf, double* input_sup, expr_t** input_lexpr, expr_t** input_uexpr, const size_t size)
+{
+    for(size_t n = 0; n < size; n++)
+    {
+        expr_t* expr = expr_array[n];
+
+        double res_inf = expr->inf_cst;
+
+        if((expr->inf_coeff == nullptr) || (expr->sup_coeff == nullptr))
+        {
+            lb_array[n] = 0;
+
+            continue;
+        }
+
+        double tmp1, tmp2;
+        size_t k;
+
+        for(size_t i = 0; i < expr->size; i++)
+        {
+            if(expr->type == DENSE)
+            {
+                k = i;
+            }
+            else
+            {
+                k = expr->dim[i];
+            }
+
             elina_double_interval_mul(&tmp1, &tmp2, expr->inf_coeff[i], expr->sup_coeff[i], input_inf[k], input_sup[k]);
-            res->inf_cst = res->inf_cst + tmp1;
-            res->sup_cst = res->sup_cst - tmp1;
-        }
-    }
-
-    res->inf_cst = res->inf_cst + expr->inf_cst;
-    res->sup_cst = res->sup_cst + expr->sup_cst;
-
-    free(expr);
-    *expr_ptr = res;
+            res_inf = res_inf + tmp1;
+        }
+
+        lb_array[n] = res_inf;
+    }
 }
 
 
 __device__ __host__
-void replace_input_poly_cons_in_uexpr(expr_t** expr_ptr, double* input_inf, double* input_sup, expr_t** input_lexpr, expr_t** input_uexpr)
-{
-    expr_t* expr = *expr_ptr;
-
-    double tmp1, tmp2;
-    expr_t* res;
-
-    size_t k;
-
-    if(expr->type == DENSE)
-    {
-        k = 0;
-    }
-    else
-    {
-        k = expr->dim[0];
-    }
-
-    expr_t * mul_expr = nullptr;
-
-    if(expr->sup_coeff[0] < 0)
-    {
-        mul_expr = input_lexpr[k];
-    }
-    else if(expr->inf_coeff[0] < 0)
-    {
-        mul_expr = input_uexpr[k];
-    }
-
-    if(mul_expr != nullptr)
-    {
-        if(mul_expr->size == 0)
-        {
-            res = multiply_cst_expr(mul_expr, expr->inf_coeff[0], expr->sup_coeff[0]);
-        }
-        else
-        {
-            res = multiply_expr(mul_expr, expr->inf_coeff[0], expr->sup_coeff[0]);
-        }
-    }
-    else
-    {
-        elina_double_interval_mul(&tmp1, &tmp2, expr->inf_coeff[0], expr->sup_coeff[0], input_inf[k], input_sup[k]);
-        res = create_cst_expr(-tmp2, tmp2);
-    }
-                //printf("finish\n");
-        //fflush(stdout);
-    for(size_t i = 1; i < expr->size; i++)
-    {
-        if(expr->type == DENSE)
-        {
-            k = i;
-        }
-        else
-        {
-            k = expr->dim[i];
-        }
-
-        expr_t* mul_expr = nullptr;
-        expr_t* sum_expr = nullptr;
-
-        if(expr->sup_coeff[i] < 0)
-        {
-            mul_expr = input_lexpr[k];
-        }
-        else if(expr->inf_coeff[i] < 0)
-        {
-            mul_expr = input_uexpr[k];
-        }
-
-        if(mul_expr != nullptr)
-        {
-            if(mul_expr->size == 0)
-            {
-                sum_expr = multiply_cst_expr(mul_expr, expr->inf_coeff[i], expr->sup_coeff[i]);
-                add_cst_expr(res, sum_expr);
-            }
-            else if((expr->inf_coeff[i] != 0) && (expr->sup_coeff[i] != 0))
-            {
-                sum_expr = multiply_expr(mul_expr, expr->inf_coeff[i], expr->sup_coeff[i]);
-                add_expr(res, sum_expr);
-            }
-                //free_expr(mul_expr);
-            if(sum_expr != nullptr)
-            {
-                free_expr(sum_expr);
-            }
-        }
-        else
-        {
+void compute_ub_from_expr(double* ub_array, expr_t** expr_array, double* input_inf, double* input_sup, expr_t** input_lexpr, expr_t** input_uexpr, const size_t size)
+{
+    for(size_t n = 0; n < size; n++)
+    {
+        expr_t* expr = expr_array[n];
+
+        double res_sup = expr->sup_cst;
+
+        if((expr->inf_coeff == nullptr) || (expr->sup_coeff == nullptr))
+        {
+            ub_array[n] = 0;
+
+            continue;
+        }
+
+        double tmp1, tmp2;
+        size_t k;
+
+        for(size_t i = 0; i < expr->size; i++)
+        {
+            if(expr->type == DENSE)
+            {
+                k = i;
+            }
+            else
+            {
+                k = expr->dim[i];
+            }
+
             elina_double_interval_mul(&tmp1, &tmp2, expr->inf_coeff[i], expr->sup_coeff[i], input_inf[k], input_sup[k]);
-            res->inf_cst = res->inf_cst - tmp2;
-            res->sup_cst = res->sup_cst + tmp2;
-        }
-    }
-
-    res->inf_cst = res->inf_cst + expr->inf_cst;
-    res->sup_cst = res->sup_cst + expr->sup_cst;
-
-    free(expr);
-    *expr_ptr = res;
-}
-
-
-__device__ __host__
-void compute_lb_from_expr(double* lb, expr_t** expr_ptr, double* input_inf, double* input_sup, expr_t** input_lexpr, expr_t** input_uexpr)
-{
-    expr_t* expr = *expr_ptr;
-
-    double res_inf = expr->inf_cst;
-
-    if((expr->inf_coeff == nullptr) || (expr->sup_coeff == nullptr))
-    {
-        *lb = 0;
-
-        return;
-    }
-
-    double tmp1, tmp2;
-    size_t k;
-
-    for(size_t i = 0; i < expr->size; i++)
-    {
-        if(expr->type == DENSE)
-        {
-            k = i;
-        }
-        else
-        {
-            k = expr->dim[i];
-        }
-
-        elina_double_interval_mul(&tmp1, &tmp2, expr->inf_coeff[i], expr->sup_coeff[i], input_inf[k], input_sup[k]);
-        res_inf = res_inf + tmp1;
-    }
-
-    if((input_lexpr != nullptr) && (input_uexpr != nullptr))
-    {
-        free_expr(expr);
-    }
-
-    *lb = res_inf;
-}
-
-
-__device__ __host__
-void compute_ub_from_expr(double* ub, expr_t** expr_ptr, double* input_inf, double* input_sup, expr_t** input_lexpr, expr_t** input_uexpr)
-{
-    expr_t* expr= *expr_ptr;
-
-    double res_sup = expr->sup_cst;
-
-    if((expr->inf_coeff == nullptr) || (expr->sup_coeff == nullptr))
-    {
-        *ub = 0;
-
-        return;
-    }
-
-    double tmp1, tmp2;
-    size_t k;
-
-    for(size_t i = 0; i < expr->size; i++)
-    {
-        if(expr->type == DENSE)
-        {
-            k = i;
-        }
-        else
-        {
-            k = expr->dim[i];
-        }
-
-        elina_double_interval_mul(&tmp1, &tmp2, expr->inf_coeff[i], expr->sup_coeff[i], input_inf[k], input_sup[k]);
-        res_sup = res_sup + tmp2;
-    }
-
-    if((input_lexpr != nullptr) && (input_uexpr != nullptr))
-    {
-        free_expr(expr);
-    }
-
-   *ub = res_sup;
+            res_sup = res_sup + tmp2;
+        }
+
+       ub_array[n] = res_sup;
+    }
 }
 
 

        if(is_lower)
        {
            expr_t** expr_ptr = &expr;
            replace_input_poly_cons_in_lexpr(expr_ptr, fp->input_inf, fp->input_sup, fp->input_lexpr, fp->input_uexpr);
        }
        else
        {
            expr_t** expr_ptr = &expr;
            replace_input_poly_cons_in_uexpr(expr_ptr, fp->input_inf, fp->input_sup, fp->input_lexpr, fp->input_uexpr);
        }
    }



void layer_compute_bounds_from_exprs(neuron_t** neurons, double* input_inf, double* input_sup, expr_t** input_lexpr, expr_t** input_uexpr, const size_t size)
{
    // allocate
    expr_t** lexpr_array = (expr_t**) malloc(size*sizeof(expr_t*));
    expr_t** uexpr_array = (expr_t**) malloc(size*sizeof(expr_t*));

    for(size_t i = 0; i < size; i++)
    {
        lexpr_array[i] = copy_expr(neurons[i]->expr);
        uexpr_array[i] = copy_expr(neurons[i]->expr);
    }

    double* lb_array = (double*) malloc(size*sizeof(double));
    double* ub_array = (double*) malloc(size*sizeof(double));

    // compute
    if((input_lexpr != nullptr) && (input_uexpr != nullptr))
    {
        replace_input_poly_cons_in_lexpr(lexpr_array, input_inf, input_sup, input_lexpr, input_uexpr, size);
        replace_input_poly_cons_in_uexpr(uexpr_array, input_inf, input_sup, input_lexpr, input_uexpr, size);
    }

    compute_lb_from_expr(lb_array, lexpr_array, input_inf, input_sup, input_lexpr, input_uexpr, size);
    compute_ub_from_expr(ub_array, uexpr_array, input_inf, input_sup, input_lexpr, input_uexpr, size);

    for(size_t i = 0; i < size; i++)
    {
        neurons[i]->lb = lb_array[i];
        neurons[i]->ub = ub_array[i];
    }

    // free
    for(size_t i = 0; i < size; i++)
    {
        free_expr(lexpr_array[i]);
        free_expr(uexpr_array[i]);
    }

    free(lexpr_array);
    free(uexpr_array);

    free(lb_array);
    free(ub_array);
}


