+ var_list = &(sys->saturated_variable_set);
+
+ xbt_swag_foreach(var, var_list) {
+ if (var->weight <= 0.0)
+ DIE_IMPOSSIBLE;
+ /* First check if some of these variables have reach their upper
+ bound and update min_usage accordingly. */
+ XBT_DEBUG
+ ("var=%d, var->bound=%f, var->weight=%f, min_usage=%f, var->bound*var->weight=%f",
+ var->id_int, var->bound, var->weight, min_usage,
+ var->bound * var->weight);
+ if ((var->bound > 0) && (var->bound * var->weight < min_usage)) {
+ if (min_bound < 0)
+ min_bound = var->bound;
+ else
+ min_bound = MIN(min_bound, var->bound);
+ XBT_DEBUG("Updated min_bound=%f", min_bound);
+ }
+ }
+
+
+ while ((var = xbt_swag_getFirst(var_list))) {
+ int i;
+
+ if (min_bound < 0) {
+ var->value = min_usage / var->weight;
+ } else {
+ if (min_bound == var->bound)
+ var->value = var->bound;
+ else {
+ xbt_swag_remove(var, var_list);
+ continue;
+ }
+ }
+ XBT_DEBUG("Min usage: %f, Var(%d)->weight: %f, Var(%d)->value: %f ",
+ min_usage, var->id_int, var->weight, var->id_int, var->value);
+
+
+ /* Update usage */
+
+ for (i = 0; i < var->cnsts_number; i++) {
+ elem = &var->cnsts[i];
+ cnst = elem->constraint;
+ if (cnst->shared) {
+ double_update(&(cnst->remaining), elem->value * var->value);
+ double_update(&(cnst->usage), elem->value / var->weight);
+ if(cnst->usage<=0 || cnst->remaining<=0) {
+ if (cnst->cnst_light) {
+ int index = (cnst->cnst_light-cnst_light_tab);
+ XBT_DEBUG("index: %d \t cnst_light_num: %d \t || \t cnst: %p \t cnst->cnst_light: %p \t cnst_light_tab: %p ",
+ index,cnst_light_num, cnst, cnst->cnst_light, cnst_light_tab);
+ cnst_light_tab[index]=cnst_light_tab[cnst_light_num-1];
+ cnst_light_tab[index].cnst->cnst_light = &cnst_light_tab[index];
+ cnst_light_num--;
+ cnst->cnst_light = NULL;
+ }
+ } else {
+ cnst->cnst_light->remaining_over_usage = cnst->remaining / cnst->usage;
+ }
+ make_elem_inactive(elem);
+ } else {
+ cnst->usage = 0.0;
+ make_elem_inactive(elem);
+ elem_list = &(cnst->element_set);
+ xbt_swag_foreach(elem, elem_list) {
+ if (elem->variable->weight <= 0 || elem->variable->value > 0)
+ break;
+ if (elem->value > 0)
+ cnst->usage = MAX(cnst->usage, elem->value / elem->variable->weight);
+ }
+ if (cnst->usage<=0 || cnst->remaining<=0) {
+ if(cnst->cnst_light) {
+ int index = (cnst->cnst_light-cnst_light_tab);
+ XBT_DEBUG("index: %d \t cnst_light_num: %d \t || \t cnst: %p \t cnst->cnst_light: %p \t cnst_light_tab: %p ",
+ index,cnst_light_num, cnst, cnst->cnst_light, cnst_light_tab);
+ cnst_light_tab[index]=cnst_light_tab[cnst_light_num-1];
+ cnst_light_tab[index].cnst->cnst_light = &cnst_light_tab[index];
+ cnst_light_num--;
+ cnst->cnst_light = NULL;
+ }
+ } else {
+ cnst->cnst_light->remaining_over_usage = cnst->remaining / cnst->usage;
+ }
+ }
+ }
+ xbt_swag_remove(var, var_list);
+ }
+
+ /* Find out which variables reach the maximum */
+ min_usage = -1;
+ min_bound = -1;
+ saturated_constraint_set->pos = 0;
+ int pos;
+ for(pos=0; pos<cnst_light_num; pos++)
+ saturated_constraint_set_update(
+ cnst_light_tab[pos].remaining_over_usage,
+ pos,
+ saturated_constraint_set,
+ &min_usage);
+
+ saturated_variable_set_update( cnst_light_tab,
+ saturated_constraint_set,
+ sys);
+
+ } while (cnst_light_num > 0);
+
+ sys->modified = 0;
+ if (sys->selective_update_active)
+ lmm_remove_all_modified_set(sys);
+
+ if (XBT_LOG_ISENABLED(surf_maxmin, xbt_log_priority_debug)) {
+ lmm_print(sys);
+ }
+
+ xbt_free(saturated_constraint_set->data);
+ xbt_free(saturated_constraint_set);
+ xbt_free(cnst_light_tab);
+ XBT_OUT();
+}
+
+/* Not a O(1) function */
+
+void lmm_update(lmm_system_t sys, lmm_constraint_t cnst,
+ lmm_variable_t var, double value)
+{
+ int i;
+
+ for (i = 0; i < var->cnsts_number; i++)
+ if (var->cnsts[i].constraint == cnst) {
+ var->cnsts[i].value = value;
+ sys->modified = 1;
+ lmm_update_modified_set(sys, cnst);
+ return;
+ }
+}
+
+/** \brief Attribute the value bound to var->bound.
+ *
+ * \param sys the lmm_system_t
+ * \param var the lmm_variable_t
+ * \param bound the new bound to associate with var
+ *
+ * Makes var->bound equal to bound. Whenever this function is called
+ * a change is signed in the system. To
+ * avoid false system changing detection it is a good idea to test
+ * (bound != 0) before calling it.
+ *
+ */
+void lmm_update_variable_bound(lmm_system_t sys, lmm_variable_t var,
+ double bound)
+{
+ sys->modified = 1;
+ var->bound = bound;
+
+ if (var->cnsts_number)
+ lmm_update_modified_set(sys, var->cnsts[0].constraint);
+}
+
+
+void lmm_update_variable_weight(lmm_system_t sys, lmm_variable_t var,
+ double weight)
+{
+ int i;
+ lmm_element_t elem;
+
+ if (weight == var->weight)
+ return;
+ XBT_IN("(sys=%p, var=%p, weight=%f)", sys, var, weight);
+ sys->modified = 1;
+ var->weight = weight;
+ xbt_swag_remove(var, &(sys->variable_set));
+ if (weight)
+ xbt_swag_insert_at_head(var, &(sys->variable_set));
+ else
+ xbt_swag_insert_at_tail(var, &(sys->variable_set));
+
+ for (i = 0; i < var->cnsts_number; i++) {
+ elem = &var->cnsts[i];
+ xbt_swag_remove(elem, &(elem->constraint->element_set));
+ if (weight)
+ xbt_swag_insert_at_head(elem, &(elem->constraint->element_set));
+ else
+ xbt_swag_insert_at_tail(elem, &(elem->constraint->element_set));
+
+ if (i == 0)
+ lmm_update_modified_set(sys, elem->constraint);
+ }
+ if (!weight)
+ var->value = 0.0;
+
+ XBT_OUT();
+}
+
+XBT_INLINE double lmm_get_variable_weight(lmm_variable_t var)
+{
+ return var->weight;
+}
+
+XBT_INLINE void lmm_update_constraint_bound(lmm_system_t sys,
+ lmm_constraint_t cnst,
+ double bound)
+{
+ sys->modified = 1;
+ lmm_update_modified_set(sys, cnst);
+ cnst->bound = bound;
+}
+
+XBT_INLINE int lmm_constraint_used(lmm_system_t sys, lmm_constraint_t cnst)
+{
+ return xbt_swag_belongs(cnst, &(sys->active_constraint_set));
+}
+
+XBT_INLINE lmm_constraint_t lmm_get_first_active_constraint(lmm_system_t
+ sys)
+{
+ return xbt_swag_getFirst(&(sys->active_constraint_set));
+}