     compute_lb_from_expr(lb_array, lexpr_array, fp->input_inf, fp->input_sup, fp->input_lexpr, fp->input_uexpr, num_out_neurons);
     compute_ub_from_expr(ub_array, uexpr_array, fp->input_inf, fp->input_sup, fp->input_lexpr, fp->input_uexpr, num_out_neurons);
 
-    for(size_t i = 0; i < num_out_neurons; i++)
-    {
-        out_neurons[i]->lb = lb_array[i];
-        out_neurons[i]->ub = ub_array[i];
-    }
+    layer_assign_bounds(out_neurons, lb_array, ub_array, num_out_neurons);
 
     free(lb_array);
     free(ub_array);


    return num_out_neurons;
}


__device__ __host__



__device__ __host__
void apply_relu_lexpr(double* lb_array, expr_t** lexpr_array, neuron_t** neurons, const size_t num_out_neurons)
{
    for(size_t n = 0; n < num_out_neurons; n++)
    {
        expr_t* lexpr = lexpr_array[n];

        const size_t size = lexpr->size;
        const double lb = neurons[n]->lb;
        const double ub = neurons[n]->ub;
        const double width = lb + ub;

        if(ub < 0)
        {
            free_expr(lexpr_array[n]);
            lexpr_array[n] = nullptr;

            lb_array[n] = 0;

            continue;
        }

        if(lb < 0)
        {
            lb_array[n] = lb;

            continue;
        }

        const double area1 = lb*ub;
        const double area2 = 0.5*ub*width;

        if(area1 < area2)
        {
            const double lambda_inf = -ub/width;
            const double lambda_sup = ub/width;

            for(size_t i = 0; i < size; i++)
            {
                //lexpr->coeff[i] = lexpr->coeff[i]*lambda;
                elina_double_interval_mul_expr_coeff(&lexpr->inf_coeff[i], &lexpr->sup_coeff[i], lambda_inf, lambda_sup, lexpr->inf_coeff[i], lexpr->sup_coeff[i]);
            }
            //lexpr->cst = lexpr->cst*lambda;
            elina_double_interval_mul_cst_coeff(&lexpr->inf_cst, &lexpr->sup_cst, lambda_inf, lambda_sup, lexpr->inf_cst, lexpr->sup_cst);
            //double res, res1;

            lb_array[n] = -(lambda_inf*lb);
        }
        else
        {
            free_expr(lexpr_array[n]);
            lexpr_array[n] = nullptr;

            lb_array[n] = 0;
        }
    }
}


__device__ __host__
void apply_relu_uexpr(double* ub_array, expr_t** uexpr_array, neuron_t** neurons, const size_t num_out_neurons)
{
    for(size_t n = 0; n < num_out_neurons; n++)
    {
        expr_t* uexpr = uexpr_array[n];

        const size_t size = uexpr->size;
        const double lb = neurons[n]->lb;
        const double ub = neurons[n]->ub;
        const double width = lb + ub;

        if(ub < 0)
        {
            free_expr(uexpr_array[n]);
            uexpr_array[n] = nullptr;

            ub_array[n] = 0;

            continue;
        }

        if(lb < 0)
        {
            ub_array[n] = ub;

            continue;
        }

        const double lambda_inf = -ub/width;
        const double lambda_sup = ub/width;

        for(size_t i = 0; i < size; i++)
        {
            //uexpr->coeff[i] = uexpr->coeff[i]*lambda;
             elina_double_interval_mul_expr_coeff(&uexpr->inf_coeff[i], &uexpr->sup_coeff[i], lambda_inf, lambda_sup, uexpr->inf_coeff[i], uexpr->sup_coeff[i]);
        }

        elina_double_interval_mul_cst_coeff(&uexpr->inf_cst, &uexpr->sup_cst, lambda_inf, lambda_sup, uexpr->inf_cst, uexpr->sup_cst);
        const double mu_inf = lambda_inf*lb;
        const double mu_sup = lambda_sup*lb;
        //uexpr->cst = uexpr->cst*lambda;
        //uexpr->cst = uexpr->cst + lambda*lb;
        uexpr->inf_cst += mu_inf;
        uexpr->sup_cst += mu_sup;

        ub_array[n] = ub;
    }
}


void assign_output_inf_sup(double* lb_array, double* ub_array, neuron_t** neurons, const size_t num_out_neurons)
{
    for(size_t i = 0; i < num_out_neurons; i++)
    {
        lb_array[i] = neurons[i]->lb;
        ub_array[i] = neurons[i]->ub;
        printf("out inf numer %i is: %f\n", i, lb_array[i]);
        printf("out sup numer %i is: %f\n", i, ub_array[i]);
    }
}


void handle_final_relu_layer(fppoly_internal_t* pr, output_abstract_t* out, neuron_t** neurons, const size_t size, const bool has_relu)
{
    if(has_relu)
    {
        apply_relu_lexpr(out->output_inf, out->lexpr, neurons, size);
        apply_relu_uexpr(out->output_sup, out->uexpr, neurons, size);
    }
    else
    {
        assign_output_inf_sup(out->output_inf, out->output_sup, neurons, size);
    }
}


void handle_final_non_relu_layer(fppoly_internal_t* pr, output_abstract_t* out, neuron_t** neurons, const size_t size)
{
    assign_output_inf_sup(out->output_inf, out->output_sup, neurons, size);
}


