OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gcc-4.5.1/] [gcc/] [omega.c] - Diff between revs 816 and 826

Only display areas with differences | Details | Blame | View Log

Rev 816 Rev 826
/* Source code for an implementation of the Omega test, an integer
/* Source code for an implementation of the Omega test, an integer
   programming algorithm for dependence analysis, by William Pugh,
   programming algorithm for dependence analysis, by William Pugh,
   appeared in Supercomputing '91 and CACM Aug 92.
   appeared in Supercomputing '91 and CACM Aug 92.
 
 
   This code has no license restrictions, and is considered public
   This code has no license restrictions, and is considered public
   domain.
   domain.
 
 
   Changes copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
   Changes copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
   Inc.
   Inc.
   Contributed by Sebastian Pop <sebastian.pop@inria.fr>
   Contributed by Sebastian Pop <sebastian.pop@inria.fr>
 
 
This file is part of GCC.
This file is part of GCC.
 
 
GCC is free software; you can redistribute it and/or modify it under
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
Software Foundation; either version 3, or (at your option) any later
version.
version.
 
 
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.
for more details.
 
 
You should have received a copy of the GNU General Public License
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */
<http://www.gnu.org/licenses/>.  */
 
 
/* For a detailed description, see "Constraint-Based Array Dependence
/* For a detailed description, see "Constraint-Based Array Dependence
   Analysis" William Pugh, David Wonnacott, TOPLAS'98 and David
   Analysis" William Pugh, David Wonnacott, TOPLAS'98 and David
   Wonnacott's thesis:
   Wonnacott's thesis:
   ftp://ftp.cs.umd.edu/pub/omega/davewThesis/davewThesis.ps.gz
   ftp://ftp.cs.umd.edu/pub/omega/davewThesis/davewThesis.ps.gz
*/
*/
 
 
#include "config.h"
#include "config.h"
#include "system.h"
#include "system.h"
#include "coretypes.h"
#include "coretypes.h"
#include "tm.h"
#include "tm.h"
#include "ggc.h"
#include "ggc.h"
#include "tree.h"
#include "tree.h"
#include "diagnostic.h"
#include "diagnostic.h"
#include "varray.h"
#include "varray.h"
#include "tree-pass.h"
#include "tree-pass.h"
#include "omega.h"
#include "omega.h"
 
 
/* When set to true, keep substitution variables.  When set to false,
/* When set to true, keep substitution variables.  When set to false,
   resurrect substitution variables (convert substitutions back to EQs).  */
   resurrect substitution variables (convert substitutions back to EQs).  */
static bool omega_reduce_with_subs = true;
static bool omega_reduce_with_subs = true;
 
 
/* When set to true, omega_simplify_problem checks for problem with no
/* When set to true, omega_simplify_problem checks for problem with no
   solutions, calling verify_omega_pb.  */
   solutions, calling verify_omega_pb.  */
static bool omega_verify_simplification = false;
static bool omega_verify_simplification = false;
 
 
/* When set to true, only produce a single simplified result.  */
/* When set to true, only produce a single simplified result.  */
static bool omega_single_result = false;
static bool omega_single_result = false;
 
 
/* Set return_single_result to 1 when omega_single_result is true.  */
/* Set return_single_result to 1 when omega_single_result is true.  */
static int return_single_result = 0;
static int return_single_result = 0;
 
 
/* Hash table for equations generated by the solver.  */
/* Hash table for equations generated by the solver.  */
#define HASH_TABLE_SIZE PARAM_VALUE (PARAM_OMEGA_HASH_TABLE_SIZE)
#define HASH_TABLE_SIZE PARAM_VALUE (PARAM_OMEGA_HASH_TABLE_SIZE)
#define MAX_KEYS PARAM_VALUE (PARAM_OMEGA_MAX_KEYS)
#define MAX_KEYS PARAM_VALUE (PARAM_OMEGA_MAX_KEYS)
static eqn hash_master;
static eqn hash_master;
static int next_key;
static int next_key;
static int hash_version = 0;
static int hash_version = 0;
 
 
/* Set to true for making the solver enter in approximation mode.  */
/* Set to true for making the solver enter in approximation mode.  */
static bool in_approximate_mode = false;
static bool in_approximate_mode = false;
 
 
/* When set to zero, the solver is allowed to add new equalities to
/* When set to zero, the solver is allowed to add new equalities to
   the problem to be solved.  */
   the problem to be solved.  */
static int conservative = 0;
static int conservative = 0;
 
 
/* Set to omega_true when the problem was successfully reduced, set to
/* Set to omega_true when the problem was successfully reduced, set to
   omega_unknown when the solver is unable to determine an answer.  */
   omega_unknown when the solver is unable to determine an answer.  */
static enum omega_result omega_found_reduction;
static enum omega_result omega_found_reduction;
 
 
/* Set to true when the solver is allowed to add omega_red equations.  */
/* Set to true when the solver is allowed to add omega_red equations.  */
static bool create_color = false;
static bool create_color = false;
 
 
/* Set to nonzero when the problem to be solved can be reduced.  */
/* Set to nonzero when the problem to be solved can be reduced.  */
static int may_be_red = 0;
static int may_be_red = 0;
 
 
/* When false, there should be no substitution equations in the
/* When false, there should be no substitution equations in the
   simplified problem.  */
   simplified problem.  */
static int please_no_equalities_in_simplified_problems = 0;
static int please_no_equalities_in_simplified_problems = 0;
 
 
/* Variables names for pretty printing.  */
/* Variables names for pretty printing.  */
static char wild_name[200][40];
static char wild_name[200][40];
 
 
/* Pointer to the void problem.  */
/* Pointer to the void problem.  */
static omega_pb no_problem = (omega_pb) 0;
static omega_pb no_problem = (omega_pb) 0;
 
 
/* Pointer to the problem to be solved.  */
/* Pointer to the problem to be solved.  */
static omega_pb original_problem = (omega_pb) 0;
static omega_pb original_problem = (omega_pb) 0;
 
 
 
 
/* Return the integer A divided by B.  */
/* Return the integer A divided by B.  */
 
 
static inline int
static inline int
int_div (int a, int b)
int_div (int a, int b)
{
{
  if (a > 0)
  if (a > 0)
    return a/b;
    return a/b;
  else
  else
    return -((-a + b - 1)/b);
    return -((-a + b - 1)/b);
}
}
 
 
/* Return the integer A modulo B.  */
/* Return the integer A modulo B.  */
 
 
static inline int
static inline int
int_mod (int a, int b)
int_mod (int a, int b)
{
{
  return a - b * int_div (a, b);
  return a - b * int_div (a, b);
}
}
 
 
/* For X and Y positive integers, return X multiplied by Y and check
/* For X and Y positive integers, return X multiplied by Y and check
   that the result does not overflow.  */
   that the result does not overflow.  */
 
 
static inline int
static inline int
check_pos_mul (int x, int y)
check_pos_mul (int x, int y)
{
{
  if (x != 0)
  if (x != 0)
    gcc_assert ((INT_MAX) / x > y);
    gcc_assert ((INT_MAX) / x > y);
 
 
  return x * y;
  return x * y;
}
}
 
 
/* Return X multiplied by Y and check that the result does not
/* Return X multiplied by Y and check that the result does not
   overflow.  */
   overflow.  */
 
 
static inline int
static inline int
check_mul (int x, int y)
check_mul (int x, int y)
{
{
  if (x >= 0)
  if (x >= 0)
    {
    {
      if (y >= 0)
      if (y >= 0)
        return check_pos_mul (x, y);
        return check_pos_mul (x, y);
      else
      else
        return -check_pos_mul (x, -y);
        return -check_pos_mul (x, -y);
    }
    }
  else if (y >= 0)
  else if (y >= 0)
    return -check_pos_mul (-x, y);
    return -check_pos_mul (-x, y);
  else
  else
    return check_pos_mul (-x, -y);
    return check_pos_mul (-x, -y);
}
}
 
 
/* Test whether equation E is red.  */
/* Test whether equation E is red.  */
 
 
static inline bool
static inline bool
omega_eqn_is_red (eqn e, int desired_res)
omega_eqn_is_red (eqn e, int desired_res)
{
{
  return (desired_res == omega_simplify && e->color == omega_red);
  return (desired_res == omega_simplify && e->color == omega_red);
}
}
 
 
/* Return a string for VARIABLE.  */
/* Return a string for VARIABLE.  */
 
 
static inline char *
static inline char *
omega_var_to_str (int variable)
omega_var_to_str (int variable)
{
{
  if (0 <= variable && variable <= 20)
  if (0 <= variable && variable <= 20)
    return wild_name[variable];
    return wild_name[variable];
 
 
  if (-20 < variable && variable < 0)
  if (-20 < variable && variable < 0)
    return wild_name[40 + variable];
    return wild_name[40 + variable];
 
 
  /* Collapse all the entries that would have overflowed.  */
  /* Collapse all the entries that would have overflowed.  */
  return wild_name[21];
  return wild_name[21];
}
}
 
 
/* Return a string for variable I in problem PB.  */
/* Return a string for variable I in problem PB.  */
 
 
static inline char *
static inline char *
omega_variable_to_str (omega_pb pb, int i)
omega_variable_to_str (omega_pb pb, int i)
{
{
  return omega_var_to_str (pb->var[i]);
  return omega_var_to_str (pb->var[i]);
}
}
 
 
/* Do nothing function: used for default initializations.  */
/* Do nothing function: used for default initializations.  */
 
 
void
void
omega_no_procedure (omega_pb pb ATTRIBUTE_UNUSED)
omega_no_procedure (omega_pb pb ATTRIBUTE_UNUSED)
{
{
}
}
 
 
void (*omega_when_reduced) (omega_pb) = omega_no_procedure;
void (*omega_when_reduced) (omega_pb) = omega_no_procedure;
 
 
/* Compute the greatest common divisor of A and B.  */
/* Compute the greatest common divisor of A and B.  */
 
 
static inline int
static inline int
gcd (int b, int a)
gcd (int b, int a)
{
{
  if (b == 1)
  if (b == 1)
    return 1;
    return 1;
 
 
  while (b != 0)
  while (b != 0)
    {
    {
      int t = b;
      int t = b;
      b = a % b;
      b = a % b;
      a = t;
      a = t;
    }
    }
 
 
  return a;
  return a;
}
}
 
 
/* Print to FILE from PB equation E with all its coefficients
/* Print to FILE from PB equation E with all its coefficients
   multiplied by C.  */
   multiplied by C.  */
 
 
static void
static void
omega_print_term (FILE *file, omega_pb pb, eqn e, int c)
omega_print_term (FILE *file, omega_pb pb, eqn e, int c)
{
{
  int i;
  int i;
  bool first = true;
  bool first = true;
  int n = pb->num_vars;
  int n = pb->num_vars;
  int went_first = -1;
  int went_first = -1;
 
 
  for (i = 1; i <= n; i++)
  for (i = 1; i <= n; i++)
    if (c * e->coef[i] > 0)
    if (c * e->coef[i] > 0)
      {
      {
        first = false;
        first = false;
        went_first = i;
        went_first = i;
 
 
        if (c * e->coef[i] == 1)
        if (c * e->coef[i] == 1)
          fprintf (file, "%s", omega_variable_to_str (pb, i));
          fprintf (file, "%s", omega_variable_to_str (pb, i));
        else
        else
          fprintf (file, "%d * %s", c * e->coef[i],
          fprintf (file, "%d * %s", c * e->coef[i],
                   omega_variable_to_str (pb, i));
                   omega_variable_to_str (pb, i));
        break;
        break;
      }
      }
 
 
  for (i = 1; i <= n; i++)
  for (i = 1; i <= n; i++)
    if (i != went_first && c * e->coef[i] != 0)
    if (i != went_first && c * e->coef[i] != 0)
      {
      {
        if (!first && c * e->coef[i] > 0)
        if (!first && c * e->coef[i] > 0)
          fprintf (file, " + ");
          fprintf (file, " + ");
 
 
        first = false;
        first = false;
 
 
        if (c * e->coef[i] == 1)
        if (c * e->coef[i] == 1)
          fprintf (file, "%s", omega_variable_to_str (pb, i));
          fprintf (file, "%s", omega_variable_to_str (pb, i));
        else if (c * e->coef[i] == -1)
        else if (c * e->coef[i] == -1)
          fprintf (file, " - %s", omega_variable_to_str (pb, i));
          fprintf (file, " - %s", omega_variable_to_str (pb, i));
        else
        else
          fprintf (file, "%d * %s", c * e->coef[i],
          fprintf (file, "%d * %s", c * e->coef[i],
                   omega_variable_to_str (pb, i));
                   omega_variable_to_str (pb, i));
      }
      }
 
 
  if (!first && c * e->coef[0] > 0)
  if (!first && c * e->coef[0] > 0)
    fprintf (file, " + ");
    fprintf (file, " + ");
 
 
  if (first || c * e->coef[0] != 0)
  if (first || c * e->coef[0] != 0)
    fprintf (file, "%d", c * e->coef[0]);
    fprintf (file, "%d", c * e->coef[0]);
}
}
 
 
/* Print to FILE the equation E of problem PB.  */
/* Print to FILE the equation E of problem PB.  */
 
 
void
void
omega_print_eqn (FILE *file, omega_pb pb, eqn e, bool test, int extra)
omega_print_eqn (FILE *file, omega_pb pb, eqn e, bool test, int extra)
{
{
  int i;
  int i;
  int n = pb->num_vars + extra;
  int n = pb->num_vars + extra;
  bool is_lt = test && e->coef[0] == -1;
  bool is_lt = test && e->coef[0] == -1;
  bool first;
  bool first;
 
 
  if (test)
  if (test)
    {
    {
      if (e->touched)
      if (e->touched)
        fprintf (file, "!");
        fprintf (file, "!");
 
 
      else if (e->key != 0)
      else if (e->key != 0)
        fprintf (file, "%d: ", e->key);
        fprintf (file, "%d: ", e->key);
    }
    }
 
 
  if (e->color == omega_red)
  if (e->color == omega_red)
    fprintf (file, "[");
    fprintf (file, "[");
 
 
  first = true;
  first = true;
 
 
  for (i = is_lt ? 1 : 0; i <= n; i++)
  for (i = is_lt ? 1 : 0; i <= n; i++)
    if (e->coef[i] < 0)
    if (e->coef[i] < 0)
      {
      {
        if (!first)
        if (!first)
          fprintf (file, " + ");
          fprintf (file, " + ");
        else
        else
          first = false;
          first = false;
 
 
        if (i == 0)
        if (i == 0)
          fprintf (file, "%d", -e->coef[i]);
          fprintf (file, "%d", -e->coef[i]);
        else if (e->coef[i] == -1)
        else if (e->coef[i] == -1)
          fprintf (file, "%s", omega_variable_to_str (pb, i));
          fprintf (file, "%s", omega_variable_to_str (pb, i));
        else
        else
          fprintf (file, "%d * %s", -e->coef[i],
          fprintf (file, "%d * %s", -e->coef[i],
                   omega_variable_to_str (pb, i));
                   omega_variable_to_str (pb, i));
      }
      }
 
 
  if (first)
  if (first)
    {
    {
      if (is_lt)
      if (is_lt)
        {
        {
          fprintf (file, "1");
          fprintf (file, "1");
          is_lt = false;
          is_lt = false;
        }
        }
      else
      else
        fprintf (file, "0");
        fprintf (file, "0");
    }
    }
 
 
  if (test == 0)
  if (test == 0)
    fprintf (file, " = ");
    fprintf (file, " = ");
  else if (is_lt)
  else if (is_lt)
    fprintf (file, " < ");
    fprintf (file, " < ");
  else
  else
    fprintf (file, " <= ");
    fprintf (file, " <= ");
 
 
  first = true;
  first = true;
 
 
  for (i = 0; i <= n; i++)
  for (i = 0; i <= n; i++)
    if (e->coef[i] > 0)
    if (e->coef[i] > 0)
      {
      {
        if (!first)
        if (!first)
          fprintf (file, " + ");
          fprintf (file, " + ");
        else
        else
          first = false;
          first = false;
 
 
        if (i == 0)
        if (i == 0)
          fprintf (file, "%d", e->coef[i]);
          fprintf (file, "%d", e->coef[i]);
        else if (e->coef[i] == 1)
        else if (e->coef[i] == 1)
          fprintf (file, "%s", omega_variable_to_str (pb, i));
          fprintf (file, "%s", omega_variable_to_str (pb, i));
        else
        else
          fprintf (file, "%d * %s", e->coef[i],
          fprintf (file, "%d * %s", e->coef[i],
                   omega_variable_to_str (pb, i));
                   omega_variable_to_str (pb, i));
      }
      }
 
 
  if (first)
  if (first)
    fprintf (file, "0");
    fprintf (file, "0");
 
 
  if (e->color == omega_red)
  if (e->color == omega_red)
    fprintf (file, "]");
    fprintf (file, "]");
}
}
 
 
/* Print to FILE all the variables of problem PB.  */
/* Print to FILE all the variables of problem PB.  */
 
 
static void
static void
omega_print_vars (FILE *file, omega_pb pb)
omega_print_vars (FILE *file, omega_pb pb)
{
{
  int i;
  int i;
 
 
  fprintf (file, "variables = ");
  fprintf (file, "variables = ");
 
 
  if (pb->safe_vars > 0)
  if (pb->safe_vars > 0)
    fprintf (file, "protected (");
    fprintf (file, "protected (");
 
 
  for (i = 1; i <= pb->num_vars; i++)
  for (i = 1; i <= pb->num_vars; i++)
    {
    {
      fprintf (file, "%s", omega_variable_to_str (pb, i));
      fprintf (file, "%s", omega_variable_to_str (pb, i));
 
 
      if (i == pb->safe_vars)
      if (i == pb->safe_vars)
        fprintf (file, ")");
        fprintf (file, ")");
 
 
      if (i < pb->num_vars)
      if (i < pb->num_vars)
        fprintf (file, ", ");
        fprintf (file, ", ");
    }
    }
 
 
  fprintf (file, "\n");
  fprintf (file, "\n");
}
}
 
 
/* Debug problem PB.  */
/* Debug problem PB.  */
 
 
void
void
debug_omega_problem (omega_pb pb)
debug_omega_problem (omega_pb pb)
{
{
  omega_print_problem (stderr, pb);
  omega_print_problem (stderr, pb);
}
}
 
 
/* Print to FILE problem PB.  */
/* Print to FILE problem PB.  */
 
 
void
void
omega_print_problem (FILE *file, omega_pb pb)
omega_print_problem (FILE *file, omega_pb pb)
{
{
  int e;
  int e;
 
 
  if (!pb->variables_initialized)
  if (!pb->variables_initialized)
    omega_initialize_variables (pb);
    omega_initialize_variables (pb);
 
 
  omega_print_vars (file, pb);
  omega_print_vars (file, pb);
 
 
  for (e = 0; e < pb->num_eqs; e++)
  for (e = 0; e < pb->num_eqs; e++)
    {
    {
      omega_print_eq (file, pb, &pb->eqs[e]);
      omega_print_eq (file, pb, &pb->eqs[e]);
      fprintf (file, "\n");
      fprintf (file, "\n");
    }
    }
 
 
  fprintf (file, "Done with EQ\n");
  fprintf (file, "Done with EQ\n");
 
 
  for (e = 0; e < pb->num_geqs; e++)
  for (e = 0; e < pb->num_geqs; e++)
    {
    {
      omega_print_geq (file, pb, &pb->geqs[e]);
      omega_print_geq (file, pb, &pb->geqs[e]);
      fprintf (file, "\n");
      fprintf (file, "\n");
    }
    }
 
 
  fprintf (file, "Done with GEQ\n");
  fprintf (file, "Done with GEQ\n");
 
 
  for (e = 0; e < pb->num_subs; e++)
  for (e = 0; e < pb->num_subs; e++)
    {
    {
      eqn eq = &pb->subs[e];
      eqn eq = &pb->subs[e];
 
 
      if (eq->color == omega_red)
      if (eq->color == omega_red)
        fprintf (file, "[");
        fprintf (file, "[");
 
 
      if (eq->key > 0)
      if (eq->key > 0)
        fprintf (file, "%s := ", omega_var_to_str (eq->key));
        fprintf (file, "%s := ", omega_var_to_str (eq->key));
      else
      else
        fprintf (file, "#%d := ", eq->key);
        fprintf (file, "#%d := ", eq->key);
 
 
      omega_print_term (file, pb, eq, 1);
      omega_print_term (file, pb, eq, 1);
 
 
      if (eq->color == omega_red)
      if (eq->color == omega_red)
        fprintf (file, "]");
        fprintf (file, "]");
 
 
      fprintf (file, "\n");
      fprintf (file, "\n");
    }
    }
}
}
 
 
/* Return the number of equations in PB tagged omega_red.  */
/* Return the number of equations in PB tagged omega_red.  */
 
 
int
int
omega_count_red_equations (omega_pb pb)
omega_count_red_equations (omega_pb pb)
{
{
  int e, i;
  int e, i;
  int result = 0;
  int result = 0;
 
 
  for (e = 0; e < pb->num_eqs; e++)
  for (e = 0; e < pb->num_eqs; e++)
    if (pb->eqs[e].color == omega_red)
    if (pb->eqs[e].color == omega_red)
      {
      {
        for (i = pb->num_vars; i > 0; i--)
        for (i = pb->num_vars; i > 0; i--)
          if (pb->geqs[e].coef[i])
          if (pb->geqs[e].coef[i])
            break;
            break;
 
 
        if (i == 0 && pb->geqs[e].coef[0] == 1)
        if (i == 0 && pb->geqs[e].coef[0] == 1)
          return 0;
          return 0;
        else
        else
          result += 2;
          result += 2;
      }
      }
 
 
  for (e = 0; e < pb->num_geqs; e++)
  for (e = 0; e < pb->num_geqs; e++)
    if (pb->geqs[e].color == omega_red)
    if (pb->geqs[e].color == omega_red)
      result += 1;
      result += 1;
 
 
  for (e = 0; e < pb->num_subs; e++)
  for (e = 0; e < pb->num_subs; e++)
    if (pb->subs[e].color == omega_red)
    if (pb->subs[e].color == omega_red)
      result += 2;
      result += 2;
 
 
  return result;
  return result;
}
}
 
 
/* Print to FILE all the equations in PB that are tagged omega_red.  */
/* Print to FILE all the equations in PB that are tagged omega_red.  */
 
 
void
void
omega_print_red_equations (FILE *file, omega_pb pb)
omega_print_red_equations (FILE *file, omega_pb pb)
{
{
  int e;
  int e;
 
 
  if (!pb->variables_initialized)
  if (!pb->variables_initialized)
    omega_initialize_variables (pb);
    omega_initialize_variables (pb);
 
 
  omega_print_vars (file, pb);
  omega_print_vars (file, pb);
 
 
  for (e = 0; e < pb->num_eqs; e++)
  for (e = 0; e < pb->num_eqs; e++)
    if (pb->eqs[e].color == omega_red)
    if (pb->eqs[e].color == omega_red)
      {
      {
        omega_print_eq (file, pb, &pb->eqs[e]);
        omega_print_eq (file, pb, &pb->eqs[e]);
        fprintf (file, "\n");
        fprintf (file, "\n");
      }
      }
 
 
  for (e = 0; e < pb->num_geqs; e++)
  for (e = 0; e < pb->num_geqs; e++)
    if (pb->geqs[e].color == omega_red)
    if (pb->geqs[e].color == omega_red)
      {
      {
        omega_print_geq (file, pb, &pb->geqs[e]);
        omega_print_geq (file, pb, &pb->geqs[e]);
        fprintf (file, "\n");
        fprintf (file, "\n");
      }
      }
 
 
  for (e = 0; e < pb->num_subs; e++)
  for (e = 0; e < pb->num_subs; e++)
    if (pb->subs[e].color == omega_red)
    if (pb->subs[e].color == omega_red)
      {
      {
        eqn eq = &pb->subs[e];
        eqn eq = &pb->subs[e];
        fprintf (file, "[");
        fprintf (file, "[");
 
 
        if (eq->key > 0)
        if (eq->key > 0)
          fprintf (file, "%s := ", omega_var_to_str (eq->key));
          fprintf (file, "%s := ", omega_var_to_str (eq->key));
        else
        else
          fprintf (file, "#%d := ", eq->key);
          fprintf (file, "#%d := ", eq->key);
 
 
        omega_print_term (file, pb, eq, 1);
        omega_print_term (file, pb, eq, 1);
        fprintf (file, "]\n");
        fprintf (file, "]\n");
      }
      }
}
}
 
 
/* Pretty print PB to FILE.  */
/* Pretty print PB to FILE.  */
 
 
void
void
omega_pretty_print_problem (FILE *file, omega_pb pb)
omega_pretty_print_problem (FILE *file, omega_pb pb)
{
{
  int e, v, v1, v2, v3, t;
  int e, v, v1, v2, v3, t;
  bool *live = XNEWVEC (bool, OMEGA_MAX_GEQS);
  bool *live = XNEWVEC (bool, OMEGA_MAX_GEQS);
  int stuffPrinted = 0;
  int stuffPrinted = 0;
  bool change;
  bool change;
 
 
  typedef enum {
  typedef enum {
    none, le, lt
    none, le, lt
  } partial_order_type;
  } partial_order_type;
 
 
  partial_order_type **po = XNEWVEC (partial_order_type *,
  partial_order_type **po = XNEWVEC (partial_order_type *,
                                     OMEGA_MAX_VARS * OMEGA_MAX_VARS);
                                     OMEGA_MAX_VARS * OMEGA_MAX_VARS);
  int **po_eq = XNEWVEC (int *, OMEGA_MAX_VARS * OMEGA_MAX_VARS);
  int **po_eq = XNEWVEC (int *, OMEGA_MAX_VARS * OMEGA_MAX_VARS);
  int *last_links = XNEWVEC (int, OMEGA_MAX_VARS);
  int *last_links = XNEWVEC (int, OMEGA_MAX_VARS);
  int *first_links = XNEWVEC (int, OMEGA_MAX_VARS);
  int *first_links = XNEWVEC (int, OMEGA_MAX_VARS);
  int *chain_length = XNEWVEC (int, OMEGA_MAX_VARS);
  int *chain_length = XNEWVEC (int, OMEGA_MAX_VARS);
  int *chain = XNEWVEC (int, OMEGA_MAX_VARS);
  int *chain = XNEWVEC (int, OMEGA_MAX_VARS);
  int i, m;
  int i, m;
  bool multiprint;
  bool multiprint;
 
 
  if (!pb->variables_initialized)
  if (!pb->variables_initialized)
    omega_initialize_variables (pb);
    omega_initialize_variables (pb);
 
 
  if (pb->num_vars > 0)
  if (pb->num_vars > 0)
    {
    {
      omega_eliminate_redundant (pb, false);
      omega_eliminate_redundant (pb, false);
 
 
      for (e = 0; e < pb->num_eqs; e++)
      for (e = 0; e < pb->num_eqs; e++)
        {
        {
          if (stuffPrinted)
          if (stuffPrinted)
            fprintf (file, "; ");
            fprintf (file, "; ");
 
 
          stuffPrinted = 1;
          stuffPrinted = 1;
          omega_print_eq (file, pb, &pb->eqs[e]);
          omega_print_eq (file, pb, &pb->eqs[e]);
        }
        }
 
 
      for (e = 0; e < pb->num_geqs; e++)
      for (e = 0; e < pb->num_geqs; e++)
        live[e] = true;
        live[e] = true;
 
 
      while (1)
      while (1)
        {
        {
          for (v = 1; v <= pb->num_vars; v++)
          for (v = 1; v <= pb->num_vars; v++)
            {
            {
              last_links[v] = first_links[v] = 0;
              last_links[v] = first_links[v] = 0;
              chain_length[v] = 0;
              chain_length[v] = 0;
 
 
              for (v2 = 1; v2 <= pb->num_vars; v2++)
              for (v2 = 1; v2 <= pb->num_vars; v2++)
                po[v][v2] = none;
                po[v][v2] = none;
            }
            }
 
 
          for (e = 0; e < pb->num_geqs; e++)
          for (e = 0; e < pb->num_geqs; e++)
            if (live[e])
            if (live[e])
              {
              {
                for (v = 1; v <= pb->num_vars; v++)
                for (v = 1; v <= pb->num_vars; v++)
                  if (pb->geqs[e].coef[v] == 1)
                  if (pb->geqs[e].coef[v] == 1)
                    first_links[v]++;
                    first_links[v]++;
                  else if (pb->geqs[e].coef[v] == -1)
                  else if (pb->geqs[e].coef[v] == -1)
                    last_links[v]++;
                    last_links[v]++;
 
 
                v1 = pb->num_vars;
                v1 = pb->num_vars;
 
 
                while (v1 > 0 && pb->geqs[e].coef[v1] == 0)
                while (v1 > 0 && pb->geqs[e].coef[v1] == 0)
                  v1--;
                  v1--;
 
 
                v2 = v1 - 1;
                v2 = v1 - 1;
 
 
                while (v2 > 0 && pb->geqs[e].coef[v2] == 0)
                while (v2 > 0 && pb->geqs[e].coef[v2] == 0)
                  v2--;
                  v2--;
 
 
                v3 = v2 - 1;
                v3 = v2 - 1;
 
 
                while (v3 > 0 && pb->geqs[e].coef[v3] == 0)
                while (v3 > 0 && pb->geqs[e].coef[v3] == 0)
                  v3--;
                  v3--;
 
 
                if (pb->geqs[e].coef[0] > 0 || pb->geqs[e].coef[0] < -1
                if (pb->geqs[e].coef[0] > 0 || pb->geqs[e].coef[0] < -1
                    || v2 <= 0 || v3 > 0
                    || v2 <= 0 || v3 > 0
                    || pb->geqs[e].coef[v1] * pb->geqs[e].coef[v2] != -1)
                    || pb->geqs[e].coef[v1] * pb->geqs[e].coef[v2] != -1)
                  {
                  {
                    /* Not a partial order relation.  */
                    /* Not a partial order relation.  */
                  }
                  }
                else
                else
                  {
                  {
                    if (pb->geqs[e].coef[v1] == 1)
                    if (pb->geqs[e].coef[v1] == 1)
                      {
                      {
                        v3 = v2;
                        v3 = v2;
                        v2 = v1;
                        v2 = v1;
                        v1 = v3;
                        v1 = v3;
                      }
                      }
 
 
                    /* Relation is v1 <= v2 or v1 < v2.  */
                    /* Relation is v1 <= v2 or v1 < v2.  */
                    po[v1][v2] = ((pb->geqs[e].coef[0] == 0) ? le : lt);
                    po[v1][v2] = ((pb->geqs[e].coef[0] == 0) ? le : lt);
                    po_eq[v1][v2] = e;
                    po_eq[v1][v2] = e;
                  }
                  }
              }
              }
          for (v = 1; v <= pb->num_vars; v++)
          for (v = 1; v <= pb->num_vars; v++)
            chain_length[v] = last_links[v];
            chain_length[v] = last_links[v];
 
 
          /* Just in case pb->num_vars <= 0.  */
          /* Just in case pb->num_vars <= 0.  */
          change = false;
          change = false;
          for (t = 0; t < pb->num_vars; t++)
          for (t = 0; t < pb->num_vars; t++)
            {
            {
              change = false;
              change = false;
 
 
              for (v1 = 1; v1 <= pb->num_vars; v1++)
              for (v1 = 1; v1 <= pb->num_vars; v1++)
                for (v2 = 1; v2 <= pb->num_vars; v2++)
                for (v2 = 1; v2 <= pb->num_vars; v2++)
                  if (po[v1][v2] != none &&
                  if (po[v1][v2] != none &&
                      chain_length[v1] <= chain_length[v2])
                      chain_length[v1] <= chain_length[v2])
                    {
                    {
                      chain_length[v1] = chain_length[v2] + 1;
                      chain_length[v1] = chain_length[v2] + 1;
                      change = true;
                      change = true;
                    }
                    }
            }
            }
 
 
          /* Caught in cycle.  */
          /* Caught in cycle.  */
          gcc_assert (!change);
          gcc_assert (!change);
 
 
          for (v1 = 1; v1 <= pb->num_vars; v1++)
          for (v1 = 1; v1 <= pb->num_vars; v1++)
            if (chain_length[v1] == 0)
            if (chain_length[v1] == 0)
              first_links[v1] = 0;
              first_links[v1] = 0;
 
 
          v = 1;
          v = 1;
 
 
          for (v1 = 2; v1 <= pb->num_vars; v1++)
          for (v1 = 2; v1 <= pb->num_vars; v1++)
            if (chain_length[v1] + first_links[v1] >
            if (chain_length[v1] + first_links[v1] >
                chain_length[v] + first_links[v])
                chain_length[v] + first_links[v])
              v = v1;
              v = v1;
 
 
          if (chain_length[v] + first_links[v] == 0)
          if (chain_length[v] + first_links[v] == 0)
            break;
            break;
 
 
          if (stuffPrinted)
          if (stuffPrinted)
            fprintf (file, "; ");
            fprintf (file, "; ");
 
 
          stuffPrinted = 1;
          stuffPrinted = 1;
 
 
          /* Chain starts at v. */
          /* Chain starts at v. */
          {
          {
            int tmp;
            int tmp;
            bool first = true;
            bool first = true;
 
 
            for (e = 0; e < pb->num_geqs; e++)
            for (e = 0; e < pb->num_geqs; e++)
              if (live[e] && pb->geqs[e].coef[v] == 1)
              if (live[e] && pb->geqs[e].coef[v] == 1)
                {
                {
                  if (!first)
                  if (!first)
                    fprintf (file, ", ");
                    fprintf (file, ", ");
 
 
                  tmp = pb->geqs[e].coef[v];
                  tmp = pb->geqs[e].coef[v];
                  pb->geqs[e].coef[v] = 0;
                  pb->geqs[e].coef[v] = 0;
                  omega_print_term (file, pb, &pb->geqs[e], -1);
                  omega_print_term (file, pb, &pb->geqs[e], -1);
                  pb->geqs[e].coef[v] = tmp;
                  pb->geqs[e].coef[v] = tmp;
                  live[e] = false;
                  live[e] = false;
                  first = false;
                  first = false;
                }
                }
 
 
            if (!first)
            if (!first)
              fprintf (file, " <= ");
              fprintf (file, " <= ");
          }
          }
 
 
          /* Find chain.  */
          /* Find chain.  */
          chain[0] = v;
          chain[0] = v;
          m = 1;
          m = 1;
          while (1)
          while (1)
            {
            {
              /* Print chain.  */
              /* Print chain.  */
              for (v2 = 1; v2 <= pb->num_vars; v2++)
              for (v2 = 1; v2 <= pb->num_vars; v2++)
                if (po[v][v2] && chain_length[v] == 1 + chain_length[v2])
                if (po[v][v2] && chain_length[v] == 1 + chain_length[v2])
                  break;
                  break;
 
 
              if (v2 > pb->num_vars)
              if (v2 > pb->num_vars)
                break;
                break;
 
 
              chain[m++] = v2;
              chain[m++] = v2;
              v = v2;
              v = v2;
            }
            }
 
 
          fprintf (file, "%s", omega_variable_to_str (pb, chain[0]));
          fprintf (file, "%s", omega_variable_to_str (pb, chain[0]));
 
 
          for (multiprint = false, i = 1; i < m; i++)
          for (multiprint = false, i = 1; i < m; i++)
            {
            {
              v = chain[i - 1];
              v = chain[i - 1];
              v2 = chain[i];
              v2 = chain[i];
 
 
              if (po[v][v2] == le)
              if (po[v][v2] == le)
                fprintf (file, " <= ");
                fprintf (file, " <= ");
              else
              else
                fprintf (file, " < ");
                fprintf (file, " < ");
 
 
              fprintf (file, "%s", omega_variable_to_str (pb, v2));
              fprintf (file, "%s", omega_variable_to_str (pb, v2));
              live[po_eq[v][v2]] = false;
              live[po_eq[v][v2]] = false;
 
 
              if (!multiprint && i < m - 1)
              if (!multiprint && i < m - 1)
                for (v3 = 1; v3 <= pb->num_vars; v3++)
                for (v3 = 1; v3 <= pb->num_vars; v3++)
                  {
                  {
                    if (v == v3 || v2 == v3
                    if (v == v3 || v2 == v3
                        || po[v][v2] != po[v][v3]
                        || po[v][v2] != po[v][v3]
                        || po[v2][chain[i + 1]] != po[v3][chain[i + 1]])
                        || po[v2][chain[i + 1]] != po[v3][chain[i + 1]])
                      continue;
                      continue;
 
 
                    fprintf (file, ",%s", omega_variable_to_str (pb, v3));
                    fprintf (file, ",%s", omega_variable_to_str (pb, v3));
                    live[po_eq[v][v3]] = false;
                    live[po_eq[v][v3]] = false;
                    live[po_eq[v3][chain[i + 1]]] = false;
                    live[po_eq[v3][chain[i + 1]]] = false;
                    multiprint = true;
                    multiprint = true;
                  }
                  }
              else
              else
                multiprint = false;
                multiprint = false;
            }
            }
 
 
          v = chain[m - 1];
          v = chain[m - 1];
          /* Print last_links.  */
          /* Print last_links.  */
          {
          {
            int tmp;
            int tmp;
            bool first = true;
            bool first = true;
 
 
            for (e = 0; e < pb->num_geqs; e++)
            for (e = 0; e < pb->num_geqs; e++)
              if (live[e] && pb->geqs[e].coef[v] == -1)
              if (live[e] && pb->geqs[e].coef[v] == -1)
                {
                {
                  if (!first)
                  if (!first)
                    fprintf (file, ", ");
                    fprintf (file, ", ");
                  else
                  else
                    fprintf (file, " <= ");
                    fprintf (file, " <= ");
 
 
                  tmp = pb->geqs[e].coef[v];
                  tmp = pb->geqs[e].coef[v];
                  pb->geqs[e].coef[v] = 0;
                  pb->geqs[e].coef[v] = 0;
                  omega_print_term (file, pb, &pb->geqs[e], 1);
                  omega_print_term (file, pb, &pb->geqs[e], 1);
                  pb->geqs[e].coef[v] = tmp;
                  pb->geqs[e].coef[v] = tmp;
                  live[e] = false;
                  live[e] = false;
                  first = false;
                  first = false;
                }
                }
          }
          }
        }
        }
 
 
      for (e = 0; e < pb->num_geqs; e++)
      for (e = 0; e < pb->num_geqs; e++)
        if (live[e])
        if (live[e])
          {
          {
            if (stuffPrinted)
            if (stuffPrinted)
              fprintf (file, "; ");
              fprintf (file, "; ");
            stuffPrinted = 1;
            stuffPrinted = 1;
            omega_print_geq (file, pb, &pb->geqs[e]);
            omega_print_geq (file, pb, &pb->geqs[e]);
          }
          }
 
 
      for (e = 0; e < pb->num_subs; e++)
      for (e = 0; e < pb->num_subs; e++)
        {
        {
          eqn eq = &pb->subs[e];
          eqn eq = &pb->subs[e];
 
 
          if (stuffPrinted)
          if (stuffPrinted)
            fprintf (file, "; ");
            fprintf (file, "; ");
 
 
          stuffPrinted = 1;
          stuffPrinted = 1;
 
 
          if (eq->key > 0)
          if (eq->key > 0)
            fprintf (file, "%s := ", omega_var_to_str (eq->key));
            fprintf (file, "%s := ", omega_var_to_str (eq->key));
          else
          else
            fprintf (file, "#%d := ", eq->key);
            fprintf (file, "#%d := ", eq->key);
 
 
          omega_print_term (file, pb, eq, 1);
          omega_print_term (file, pb, eq, 1);
        }
        }
    }
    }
 
 
  free (live);
  free (live);
  free (po);
  free (po);
  free (po_eq);
  free (po_eq);
  free (last_links);
  free (last_links);
  free (first_links);
  free (first_links);
  free (chain_length);
  free (chain_length);
  free (chain);
  free (chain);
}
}
 
 
/* Assign to variable I in PB the next wildcard name.  The name of a
/* Assign to variable I in PB the next wildcard name.  The name of a
   wildcard is a negative number.  */
   wildcard is a negative number.  */
static int next_wild_card = 0;
static int next_wild_card = 0;
 
 
static void
static void
omega_name_wild_card (omega_pb pb, int i)
omega_name_wild_card (omega_pb pb, int i)
{
{
  --next_wild_card;
  --next_wild_card;
  if (next_wild_card < -PARAM_VALUE (PARAM_OMEGA_MAX_WILD_CARDS))
  if (next_wild_card < -PARAM_VALUE (PARAM_OMEGA_MAX_WILD_CARDS))
    next_wild_card = -1;
    next_wild_card = -1;
  pb->var[i] = next_wild_card;
  pb->var[i] = next_wild_card;
}
}
 
 
/* Return the index of the last protected (or safe) variable in PB,
/* Return the index of the last protected (or safe) variable in PB,
   after having added a new wildcard variable.  */
   after having added a new wildcard variable.  */
 
 
static int
static int
omega_add_new_wild_card (omega_pb pb)
omega_add_new_wild_card (omega_pb pb)
{
{
  int e;
  int e;
  int i = ++pb->safe_vars;
  int i = ++pb->safe_vars;
  pb->num_vars++;
  pb->num_vars++;
 
 
  /* Make a free place in the protected (safe) variables, by moving
  /* Make a free place in the protected (safe) variables, by moving
     the non protected variable pointed by "I" at the end, ie. at
     the non protected variable pointed by "I" at the end, ie. at
     offset pb->num_vars.  */
     offset pb->num_vars.  */
  if (pb->num_vars != i)
  if (pb->num_vars != i)
    {
    {
      /* Move "I" for all the inequalities.  */
      /* Move "I" for all the inequalities.  */
      for (e = pb->num_geqs - 1; e >= 0; e--)
      for (e = pb->num_geqs - 1; e >= 0; e--)
        {
        {
          if (pb->geqs[e].coef[i])
          if (pb->geqs[e].coef[i])
            pb->geqs[e].touched = 1;
            pb->geqs[e].touched = 1;
 
 
          pb->geqs[e].coef[pb->num_vars] = pb->geqs[e].coef[i];
          pb->geqs[e].coef[pb->num_vars] = pb->geqs[e].coef[i];
        }
        }
 
 
      /* Move "I" for all the equalities.  */
      /* Move "I" for all the equalities.  */
      for (e = pb->num_eqs - 1; e >= 0; e--)
      for (e = pb->num_eqs - 1; e >= 0; e--)
        pb->eqs[e].coef[pb->num_vars] = pb->eqs[e].coef[i];
        pb->eqs[e].coef[pb->num_vars] = pb->eqs[e].coef[i];
 
 
      /* Move "I" for all the substitutions.  */
      /* Move "I" for all the substitutions.  */
      for (e = pb->num_subs - 1; e >= 0; e--)
      for (e = pb->num_subs - 1; e >= 0; e--)
        pb->subs[e].coef[pb->num_vars] = pb->subs[e].coef[i];
        pb->subs[e].coef[pb->num_vars] = pb->subs[e].coef[i];
 
 
      /* Move the identifier.  */
      /* Move the identifier.  */
      pb->var[pb->num_vars] = pb->var[i];
      pb->var[pb->num_vars] = pb->var[i];
    }
    }
 
 
  /* Initialize at zero all the coefficients  */
  /* Initialize at zero all the coefficients  */
  for (e = pb->num_geqs - 1; e >= 0; e--)
  for (e = pb->num_geqs - 1; e >= 0; e--)
    pb->geqs[e].coef[i] = 0;
    pb->geqs[e].coef[i] = 0;
 
 
  for (e = pb->num_eqs - 1; e >= 0; e--)
  for (e = pb->num_eqs - 1; e >= 0; e--)
    pb->eqs[e].coef[i] = 0;
    pb->eqs[e].coef[i] = 0;
 
 
  for (e = pb->num_subs - 1; e >= 0; e--)
  for (e = pb->num_subs - 1; e >= 0; e--)
    pb->subs[e].coef[i] = 0;
    pb->subs[e].coef[i] = 0;
 
 
  /* And give it a name.  */
  /* And give it a name.  */
  omega_name_wild_card (pb, i);
  omega_name_wild_card (pb, i);
  return i;
  return i;
}
}
 
 
/* Delete inequality E from problem PB that has N_VARS variables.  */
/* Delete inequality E from problem PB that has N_VARS variables.  */
 
 
static void
static void
omega_delete_geq (omega_pb pb, int e, int n_vars)
omega_delete_geq (omega_pb pb, int e, int n_vars)
{
{
  if (dump_file && (dump_flags & TDF_DETAILS))
  if (dump_file && (dump_flags & TDF_DETAILS))
    {
    {
      fprintf (dump_file, "Deleting %d (last:%d): ", e, pb->num_geqs - 1);
      fprintf (dump_file, "Deleting %d (last:%d): ", e, pb->num_geqs - 1);
      omega_print_geq (dump_file, pb, &pb->geqs[e]);
      omega_print_geq (dump_file, pb, &pb->geqs[e]);
      fprintf (dump_file, "\n");
      fprintf (dump_file, "\n");
    }
    }
 
 
  if (e < pb->num_geqs - 1)
  if (e < pb->num_geqs - 1)
    omega_copy_eqn (&pb->geqs[e], &pb->geqs[pb->num_geqs - 1], n_vars);
    omega_copy_eqn (&pb->geqs[e], &pb->geqs[pb->num_geqs - 1], n_vars);
 
 
  pb->num_geqs--;
  pb->num_geqs--;
}
}
 
 
/* Delete extra inequality E from problem PB that has N_VARS
/* Delete extra inequality E from problem PB that has N_VARS
   variables.  */
   variables.  */
 
 
static void
static void
omega_delete_geq_extra (omega_pb pb, int e, int n_vars)
omega_delete_geq_extra (omega_pb pb, int e, int n_vars)
{
{
  if (dump_file && (dump_flags & TDF_DETAILS))
  if (dump_file && (dump_flags & TDF_DETAILS))
    {
    {
      fprintf (dump_file, "Deleting %d: ",e);
      fprintf (dump_file, "Deleting %d: ",e);
      omega_print_geq_extra (dump_file, pb, &pb->geqs[e]);
      omega_print_geq_extra (dump_file, pb, &pb->geqs[e]);
      fprintf (dump_file, "\n");
      fprintf (dump_file, "\n");
    }
    }
 
 
  if (e < pb->num_geqs - 1)
  if (e < pb->num_geqs - 1)
    omega_copy_eqn (&pb->geqs[e], &pb->geqs[pb->num_geqs - 1], n_vars);
    omega_copy_eqn (&pb->geqs[e], &pb->geqs[pb->num_geqs - 1], n_vars);
 
 
  pb->num_geqs--;
  pb->num_geqs--;
}
}
 
 
 
 
/* Remove variable I from problem PB.  */
/* Remove variable I from problem PB.  */
 
 
static void
static void
omega_delete_variable (omega_pb pb, int i)
omega_delete_variable (omega_pb pb, int i)
{
{
  int n_vars = pb->num_vars;
  int n_vars = pb->num_vars;
  int e;
  int e;
 
 
  if (omega_safe_var_p (pb, i))
  if (omega_safe_var_p (pb, i))
    {
    {
      int j = pb->safe_vars;
      int j = pb->safe_vars;
 
 
      for (e = pb->num_geqs - 1; e >= 0; e--)
      for (e = pb->num_geqs - 1; e >= 0; e--)
        {
        {
          pb->geqs[e].touched = 1;
          pb->geqs[e].touched = 1;
          pb->geqs[e].coef[i] = pb->geqs[e].coef[j];
          pb->geqs[e].coef[i] = pb->geqs[e].coef[j];
          pb->geqs[e].coef[j] = pb->geqs[e].coef[n_vars];
          pb->geqs[e].coef[j] = pb->geqs[e].coef[n_vars];
        }
        }
 
 
      for (e = pb->num_eqs - 1; e >= 0; e--)
      for (e = pb->num_eqs - 1; e >= 0; e--)
        {
        {
          pb->eqs[e].coef[i] = pb->eqs[e].coef[j];
          pb->eqs[e].coef[i] = pb->eqs[e].coef[j];
          pb->eqs[e].coef[j] = pb->eqs[e].coef[n_vars];
          pb->eqs[e].coef[j] = pb->eqs[e].coef[n_vars];
        }
        }
 
 
      for (e = pb->num_subs - 1; e >= 0; e--)
      for (e = pb->num_subs - 1; e >= 0; e--)
        {
        {
          pb->subs[e].coef[i] = pb->subs[e].coef[j];
          pb->subs[e].coef[i] = pb->subs[e].coef[j];
          pb->subs[e].coef[j] = pb->subs[e].coef[n_vars];
          pb->subs[e].coef[j] = pb->subs[e].coef[n_vars];
        }
        }
 
 
      pb->var[i] = pb->var[j];
      pb->var[i] = pb->var[j];
      pb->var[j] = pb->var[n_vars];
      pb->var[j] = pb->var[n_vars];
    }
    }
  else if (i < n_vars)
  else if (i < n_vars)
    {
    {
      for (e = pb->num_geqs - 1; e >= 0; e--)
      for (e = pb->num_geqs - 1; e >= 0; e--)
        if (pb->geqs[e].coef[n_vars])
        if (pb->geqs[e].coef[n_vars])
          {
          {
            pb->geqs[e].coef[i] = pb->geqs[e].coef[n_vars];
            pb->geqs[e].coef[i] = pb->geqs[e].coef[n_vars];
            pb->geqs[e].touched = 1;
            pb->geqs[e].touched = 1;
          }
          }
 
 
      for (e = pb->num_eqs - 1; e >= 0; e--)
      for (e = pb->num_eqs - 1; e >= 0; e--)
        pb->eqs[e].coef[i] = pb->eqs[e].coef[n_vars];
        pb->eqs[e].coef[i] = pb->eqs[e].coef[n_vars];
 
 
      for (e = pb->num_subs - 1; e >= 0; e--)
      for (e = pb->num_subs - 1; e >= 0; e--)
        pb->subs[e].coef[i] = pb->subs[e].coef[n_vars];
        pb->subs[e].coef[i] = pb->subs[e].coef[n_vars];
 
 
      pb->var[i] = pb->var[n_vars];
      pb->var[i] = pb->var[n_vars];
    }
    }
 
 
  if (omega_safe_var_p (pb, i))
  if (omega_safe_var_p (pb, i))
    pb->safe_vars--;
    pb->safe_vars--;
 
 
  pb->num_vars--;
  pb->num_vars--;
}
}
 
 
/* Because the coefficients of an equation are sparse, PACKING records
/* Because the coefficients of an equation are sparse, PACKING records
   indices for non null coefficients.  */
   indices for non null coefficients.  */
static int *packing;
static int *packing;
 
 
/* Set up the coefficients of PACKING, following the coefficients of
/* Set up the coefficients of PACKING, following the coefficients of
   equation EQN that has NUM_VARS variables.  */
   equation EQN that has NUM_VARS variables.  */
 
 
static inline int
static inline int
setup_packing (eqn eqn, int num_vars)
setup_packing (eqn eqn, int num_vars)
{
{
  int k;
  int k;
  int n = 0;
  int n = 0;
 
 
  for (k = num_vars; k >= 0; k--)
  for (k = num_vars; k >= 0; k--)
    if (eqn->coef[k])
    if (eqn->coef[k])
      packing[n++] = k;
      packing[n++] = k;
 
 
  return n;
  return n;
}
}
 
 
/* Computes a linear combination of EQ and SUB at VAR with coefficient
/* Computes a linear combination of EQ and SUB at VAR with coefficient
   C, such that EQ->coef[VAR] is set to 0.  TOP_VAR is the number of
   C, such that EQ->coef[VAR] is set to 0.  TOP_VAR is the number of
   non null indices of SUB stored in PACKING.  */
   non null indices of SUB stored in PACKING.  */
 
 
static inline void
static inline void
omega_substitute_red_1 (eqn eq, eqn sub, int var, int c, bool *found_black,
omega_substitute_red_1 (eqn eq, eqn sub, int var, int c, bool *found_black,
                        int top_var)
                        int top_var)
{
{
  if (eq->coef[var] != 0)
  if (eq->coef[var] != 0)
    {
    {
      if (eq->color == omega_black)
      if (eq->color == omega_black)
        *found_black = true;
        *found_black = true;
      else
      else
        {
        {
          int j, k = eq->coef[var];
          int j, k = eq->coef[var];
 
 
          eq->coef[var] = 0;
          eq->coef[var] = 0;
 
 
          for (j = top_var; j >= 0; j--)
          for (j = top_var; j >= 0; j--)
            eq->coef[packing[j]] -= sub->coef[packing[j]] * k * c;
            eq->coef[packing[j]] -= sub->coef[packing[j]] * k * c;
        }
        }
    }
    }
}
}
 
 
/* Substitute in PB variable VAR with "C * SUB".  */
/* Substitute in PB variable VAR with "C * SUB".  */
 
 
static void
static void
omega_substitute_red (omega_pb pb, eqn sub, int var, int c, bool *found_black)
omega_substitute_red (omega_pb pb, eqn sub, int var, int c, bool *found_black)
{
{
  int e, top_var = setup_packing (sub, pb->num_vars);
  int e, top_var = setup_packing (sub, pb->num_vars);
 
 
  *found_black = false;
  *found_black = false;
 
 
  if (dump_file && (dump_flags & TDF_DETAILS))
  if (dump_file && (dump_flags & TDF_DETAILS))
    {
    {
      if (sub->color == omega_red)
      if (sub->color == omega_red)
        fprintf (dump_file, "[");
        fprintf (dump_file, "[");
 
 
      fprintf (dump_file, "substituting using %s := ",
      fprintf (dump_file, "substituting using %s := ",
               omega_variable_to_str (pb, var));
               omega_variable_to_str (pb, var));
      omega_print_term (dump_file, pb, sub, -c);
      omega_print_term (dump_file, pb, sub, -c);
 
 
      if (sub->color == omega_red)
      if (sub->color == omega_red)
        fprintf (dump_file, "]");
        fprintf (dump_file, "]");
 
 
      fprintf (dump_file, "\n");
      fprintf (dump_file, "\n");
      omega_print_vars (dump_file, pb);
      omega_print_vars (dump_file, pb);
    }
    }
 
 
  for (e = pb->num_eqs - 1; e >= 0; e--)
  for (e = pb->num_eqs - 1; e >= 0; e--)
    {
    {
      eqn eqn = &(pb->eqs[e]);
      eqn eqn = &(pb->eqs[e]);
 
 
      omega_substitute_red_1 (eqn, sub, var, c, found_black, top_var);
      omega_substitute_red_1 (eqn, sub, var, c, found_black, top_var);
 
 
      if (dump_file && (dump_flags & TDF_DETAILS))
      if (dump_file && (dump_flags & TDF_DETAILS))
        {
        {
          omega_print_eq (dump_file, pb, eqn);
          omega_print_eq (dump_file, pb, eqn);
          fprintf (dump_file, "\n");
          fprintf (dump_file, "\n");
        }
        }
    }
    }
 
 
  for (e = pb->num_geqs - 1; e >= 0; e--)
  for (e = pb->num_geqs - 1; e >= 0; e--)
    {
    {
      eqn eqn = &(pb->geqs[e]);
      eqn eqn = &(pb->geqs[e]);
 
 
      omega_substitute_red_1 (eqn, sub, var, c, found_black, top_var);
      omega_substitute_red_1 (eqn, sub, var, c, found_black, top_var);
 
 
      if (eqn->coef[var] && eqn->color == omega_red)
      if (eqn->coef[var] && eqn->color == omega_red)
        eqn->touched = 1;
        eqn->touched = 1;
 
 
      if (dump_file && (dump_flags & TDF_DETAILS))
      if (dump_file && (dump_flags & TDF_DETAILS))
        {
        {
          omega_print_geq (dump_file, pb, eqn);
          omega_print_geq (dump_file, pb, eqn);
          fprintf (dump_file, "\n");
          fprintf (dump_file, "\n");
        }
        }
    }
    }
 
 
  for (e = pb->num_subs - 1; e >= 0; e--)
  for (e = pb->num_subs - 1; e >= 0; e--)
    {
    {
      eqn eqn = &(pb->subs[e]);
      eqn eqn = &(pb->subs[e]);
 
 
      omega_substitute_red_1 (eqn, sub, var, c, found_black, top_var);
      omega_substitute_red_1 (eqn, sub, var, c, found_black, top_var);
 
 
      if (dump_file && (dump_flags & TDF_DETAILS))
      if (dump_file && (dump_flags & TDF_DETAILS))
        {
        {
          fprintf (dump_file, "%s := ", omega_var_to_str (eqn->key));
          fprintf (dump_file, "%s := ", omega_var_to_str (eqn->key));
          omega_print_term (dump_file, pb, eqn, 1);
          omega_print_term (dump_file, pb, eqn, 1);
          fprintf (dump_file, "\n");
          fprintf (dump_file, "\n");
        }
        }
    }
    }
 
 
  if (dump_file && (dump_flags & TDF_DETAILS))
  if (dump_file && (dump_flags & TDF_DETAILS))
    fprintf (dump_file, "---\n\n");
    fprintf (dump_file, "---\n\n");
 
 
  if (omega_safe_var_p (pb, var) && !omega_wildcard_p (pb, var))
  if (omega_safe_var_p (pb, var) && !omega_wildcard_p (pb, var))
    *found_black = true;
    *found_black = true;
}
}
 
 
/* Substitute in PB variable VAR with "C * SUB".  */
/* Substitute in PB variable VAR with "C * SUB".  */
 
 
static void
static void
omega_substitute (omega_pb pb, eqn sub, int var, int c)
omega_substitute (omega_pb pb, eqn sub, int var, int c)
{
{
  int e, j, j0;
  int e, j, j0;
  int top_var = setup_packing (sub, pb->num_vars);
  int top_var = setup_packing (sub, pb->num_vars);
 
 
  if (dump_file && (dump_flags & TDF_DETAILS))
  if (dump_file && (dump_flags & TDF_DETAILS))
    {
    {
      fprintf (dump_file, "substituting using %s := ",
      fprintf (dump_file, "substituting using %s := ",
               omega_variable_to_str (pb, var));
               omega_variable_to_str (pb, var));
      omega_print_term (dump_file, pb, sub, -c);
      omega_print_term (dump_file, pb, sub, -c);
      fprintf (dump_file, "\n");
      fprintf (dump_file, "\n");
      omega_print_vars (dump_file, pb);
      omega_print_vars (dump_file, pb);
    }
    }
 
 
  if (top_var < 0)
  if (top_var < 0)
    {
    {
      for (e = pb->num_eqs - 1; e >= 0; e--)
      for (e = pb->num_eqs - 1; e >= 0; e--)
        pb->eqs[e].coef[var] = 0;
        pb->eqs[e].coef[var] = 0;
 
 
      for (e = pb->num_geqs - 1; e >= 0; e--)
      for (e = pb->num_geqs - 1; e >= 0; e--)
        if (pb->geqs[e].coef[var] != 0)
        if (pb->geqs[e].coef[var] != 0)
          {
          {
            pb->geqs[e].touched = 1;
            pb->geqs[e].touched = 1;
            pb->geqs[e].coef[var] = 0;
            pb->geqs[e].coef[var] = 0;
          }
          }
 
 
      for (e = pb->num_subs - 1; e >= 0; e--)
      for (e = pb->num_subs - 1; e >= 0; e--)
        pb->subs[e].coef[var] = 0;
        pb->subs[e].coef[var] = 0;
 
 
      if (omega_safe_var_p (pb, var) && !omega_wildcard_p (pb, var))
      if (omega_safe_var_p (pb, var) && !omega_wildcard_p (pb, var))
        {
        {
          int k;
          int k;
          eqn eqn = &(pb->subs[pb->num_subs++]);
          eqn eqn = &(pb->subs[pb->num_subs++]);
 
 
          for (k = pb->num_vars; k >= 0; k--)
          for (k = pb->num_vars; k >= 0; k--)
            eqn->coef[k] = 0;
            eqn->coef[k] = 0;
 
 
          eqn->key = pb->var[var];
          eqn->key = pb->var[var];
          eqn->color = omega_black;
          eqn->color = omega_black;
        }
        }
    }
    }
  else if (top_var == 0 && packing[0] == 0)
  else if (top_var == 0 && packing[0] == 0)
    {
    {
      c = -sub->coef[0] * c;
      c = -sub->coef[0] * c;
 
 
      for (e = pb->num_eqs - 1; e >= 0; e--)
      for (e = pb->num_eqs - 1; e >= 0; e--)
        {
        {
          pb->eqs[e].coef[0] += pb->eqs[e].coef[var] * c;
          pb->eqs[e].coef[0] += pb->eqs[e].coef[var] * c;
          pb->eqs[e].coef[var] = 0;
          pb->eqs[e].coef[var] = 0;
        }
        }
 
 
      for (e = pb->num_geqs - 1; e >= 0; e--)
      for (e = pb->num_geqs - 1; e >= 0; e--)
        if (pb->geqs[e].coef[var] != 0)
        if (pb->geqs[e].coef[var] != 0)
          {
          {
            pb->geqs[e].coef[0] += pb->geqs[e].coef[var] * c;
            pb->geqs[e].coef[0] += pb->geqs[e].coef[var] * c;
            pb->geqs[e].coef[var] = 0;
            pb->geqs[e].coef[var] = 0;
            pb->geqs[e].touched = 1;
            pb->geqs[e].touched = 1;
          }
          }
 
 
      for (e = pb->num_subs - 1; e >= 0; e--)
      for (e = pb->num_subs - 1; e >= 0; e--)
        {
        {
          pb->subs[e].coef[0] += pb->subs[e].coef[var] * c;
          pb->subs[e].coef[0] += pb->subs[e].coef[var] * c;
          pb->subs[e].coef[var] = 0;
          pb->subs[e].coef[var] = 0;
        }
        }
 
 
      if (omega_safe_var_p (pb, var) && !omega_wildcard_p (pb, var))
      if (omega_safe_var_p (pb, var) && !omega_wildcard_p (pb, var))
        {
        {
          int k;
          int k;
          eqn eqn = &(pb->subs[pb->num_subs++]);
          eqn eqn = &(pb->subs[pb->num_subs++]);
 
 
          for (k = pb->num_vars; k >= 1; k--)
          for (k = pb->num_vars; k >= 1; k--)
            eqn->coef[k] = 0;
            eqn->coef[k] = 0;
 
 
          eqn->coef[0] = c;
          eqn->coef[0] = c;
          eqn->key = pb->var[var];
          eqn->key = pb->var[var];
          eqn->color = omega_black;
          eqn->color = omega_black;
        }
        }
 
 
      if (dump_file && (dump_flags & TDF_DETAILS))
      if (dump_file && (dump_flags & TDF_DETAILS))
        {
        {
          fprintf (dump_file, "---\n\n");
          fprintf (dump_file, "---\n\n");
          omega_print_problem (dump_file, pb);
          omega_print_problem (dump_file, pb);
          fprintf (dump_file, "===\n\n");
          fprintf (dump_file, "===\n\n");
        }
        }
    }
    }
  else
  else
    {
    {
      for (e = pb->num_eqs - 1; e >= 0; e--)
      for (e = pb->num_eqs - 1; e >= 0; e--)
        {
        {
          eqn eqn = &(pb->eqs[e]);
          eqn eqn = &(pb->eqs[e]);
          int k = eqn->coef[var];
          int k = eqn->coef[var];
 
 
          if (k != 0)
          if (k != 0)
            {
            {
              k = c * k;
              k = c * k;
              eqn->coef[var] = 0;
              eqn->coef[var] = 0;
 
 
              for (j = top_var; j >= 0; j--)
              for (j = top_var; j >= 0; j--)
                {
                {
                  j0 = packing[j];
                  j0 = packing[j];
                  eqn->coef[j0] -= sub->coef[j0] * k;
                  eqn->coef[j0] -= sub->coef[j0] * k;
                }
                }
            }
            }
 
 
          if (dump_file && (dump_flags & TDF_DETAILS))
          if (dump_file && (dump_flags & TDF_DETAILS))
            {
            {
              omega_print_eq (dump_file, pb, eqn);
              omega_print_eq (dump_file, pb, eqn);
              fprintf (dump_file, "\n");
              fprintf (dump_file, "\n");
            }
            }
        }
        }
 
 
      for (e = pb->num_geqs - 1; e >= 0; e--)
      for (e = pb->num_geqs - 1; e >= 0; e--)
        {
        {
          eqn eqn = &(pb->geqs[e]);
          eqn eqn = &(pb->geqs[e]);
          int k = eqn->coef[var];
          int k = eqn->coef[var];
 
 
          if (k != 0)
          if (k != 0)
            {
            {
              k = c * k;
              k = c * k;
              eqn->touched = 1;
              eqn->touched = 1;
              eqn->coef[var] = 0;
              eqn->coef[var] = 0;
 
 
              for (j = top_var; j >= 0; j--)
              for (j = top_var; j >= 0; j--)
                {
                {
                  j0 = packing[j];
                  j0 = packing[j];
                  eqn->coef[j0] -= sub->coef[j0] * k;
                  eqn->coef[j0] -= sub->coef[j0] * k;
                }
                }
            }
            }
 
 
          if (dump_file && (dump_flags & TDF_DETAILS))
          if (dump_file && (dump_flags & TDF_DETAILS))
            {
            {
              omega_print_geq (dump_file, pb, eqn);
              omega_print_geq (dump_file, pb, eqn);
              fprintf (dump_file, "\n");
              fprintf (dump_file, "\n");
            }
            }
        }
        }
 
 
      for (e = pb->num_subs - 1; e >= 0; e--)
      for (e = pb->num_subs - 1; e >= 0; e--)
        {
        {
          eqn eqn = &(pb->subs[e]);
          eqn eqn = &(pb->subs[e]);
          int k = eqn->coef[var];
          int k = eqn->coef[var];
 
 
          if (k != 0)
          if (k != 0)
            {
            {
              k = c * k;
              k = c * k;
              eqn->coef[var] = 0;
              eqn->coef[var] = 0;
 
 
              for (j = top_var; j >= 0; j--)
              for (j = top_var; j >= 0; j--)
                {
                {
                  j0 = packing[j];
                  j0 = packing[j];
                  eqn->coef[j0] -= sub->coef[j0] * k;
                  eqn->coef[j0] -= sub->coef[j0] * k;
                }
                }
            }
            }
 
 
          if (dump_file && (dump_flags & TDF_DETAILS))
          if (dump_file && (dump_flags & TDF_DETAILS))
            {
            {
              fprintf (dump_file, "%s := ", omega_var_to_str (eqn->key));
              fprintf (dump_file, "%s := ", omega_var_to_str (eqn->key));
              omega_print_term (dump_file, pb, eqn, 1);
              omega_print_term (dump_file, pb, eqn, 1);
              fprintf (dump_file, "\n");
              fprintf (dump_file, "\n");
            }
            }
        }
        }
 
 
      if (dump_file && (dump_flags & TDF_DETAILS))
      if (dump_file && (dump_flags & TDF_DETAILS))
        {
        {
          fprintf (dump_file, "---\n\n");
          fprintf (dump_file, "---\n\n");
          omega_print_problem (dump_file, pb);
          omega_print_problem (dump_file, pb);
          fprintf (dump_file, "===\n\n");
          fprintf (dump_file, "===\n\n");
        }
        }
 
 
      if (omega_safe_var_p (pb, var) && !omega_wildcard_p (pb, var))
      if (omega_safe_var_p (pb, var) && !omega_wildcard_p (pb, var))
        {
        {
          int k;
          int k;
          eqn eqn = &(pb->subs[pb->num_subs++]);
          eqn eqn = &(pb->subs[pb->num_subs++]);
          c = -c;
          c = -c;
 
 
          for (k = pb->num_vars; k >= 0; k--)
          for (k = pb->num_vars; k >= 0; k--)
            eqn->coef[k] = c * (sub->coef[k]);
            eqn->coef[k] = c * (sub->coef[k]);
 
 
          eqn->key = pb->var[var];
          eqn->key = pb->var[var];
          eqn->color = sub->color;
          eqn->color = sub->color;
        }
        }
    }
    }
}
}
 
 
/* Solve e = factor alpha for x_j and substitute.  */
/* Solve e = factor alpha for x_j and substitute.  */
 
 
static void
static void
omega_do_mod (omega_pb pb, int factor, int e, int j)
omega_do_mod (omega_pb pb, int factor, int e, int j)
{
{
  int k, i;
  int k, i;
  eqn eq = omega_alloc_eqns (0, 1);
  eqn eq = omega_alloc_eqns (0, 1);
  int nfactor;
  int nfactor;
  bool kill_j = false;
  bool kill_j = false;
 
 
  omega_copy_eqn (eq, &pb->eqs[e], pb->num_vars);
  omega_copy_eqn (eq, &pb->eqs[e], pb->num_vars);
 
 
  for (k = pb->num_vars; k >= 0; k--)
  for (k = pb->num_vars; k >= 0; k--)
    {
    {
      eq->coef[k] = int_mod (eq->coef[k], factor);
      eq->coef[k] = int_mod (eq->coef[k], factor);
 
 
      if (2 * eq->coef[k] >= factor)
      if (2 * eq->coef[k] >= factor)
        eq->coef[k] -= factor;
        eq->coef[k] -= factor;
    }
    }
 
 
  nfactor = eq->coef[j];
  nfactor = eq->coef[j];
 
 
  if (omega_safe_var_p (pb, j) && !omega_wildcard_p (pb, j))
  if (omega_safe_var_p (pb, j) && !omega_wildcard_p (pb, j))
    {
    {
      i = omega_add_new_wild_card (pb);
      i = omega_add_new_wild_card (pb);
      eq->coef[pb->num_vars] = eq->coef[i];
      eq->coef[pb->num_vars] = eq->coef[i];
      eq->coef[j] = 0;
      eq->coef[j] = 0;
      eq->coef[i] = -factor;
      eq->coef[i] = -factor;
      kill_j = true;
      kill_j = true;
    }
    }
  else
  else
    {
    {
      eq->coef[j] = -factor;
      eq->coef[j] = -factor;
      if (!omega_wildcard_p (pb, j))
      if (!omega_wildcard_p (pb, j))
        omega_name_wild_card (pb, j);
        omega_name_wild_card (pb, j);
    }
    }
 
 
  omega_substitute (pb, eq, j, nfactor);
  omega_substitute (pb, eq, j, nfactor);
 
 
  for (k = pb->num_vars; k >= 0; k--)
  for (k = pb->num_vars; k >= 0; k--)
    pb->eqs[e].coef[k] = pb->eqs[e].coef[k] / factor;
    pb->eqs[e].coef[k] = pb->eqs[e].coef[k] / factor;
 
 
  if (kill_j)
  if (kill_j)
    omega_delete_variable (pb, j);
    omega_delete_variable (pb, j);
 
 
  if (dump_file && (dump_flags & TDF_DETAILS))
  if (dump_file && (dump_flags & TDF_DETAILS))
    {
    {
      fprintf (dump_file, "Mod-ing and normalizing produces:\n");
      fprintf (dump_file, "Mod-ing and normalizing produces:\n");
      omega_print_problem (dump_file, pb);
      omega_print_problem (dump_file, pb);
    }
    }
 
 
  omega_free_eqns (eq, 1);
  omega_free_eqns (eq, 1);
}
}
 
 
/* Multiplies by -1 inequality E.  */
/* Multiplies by -1 inequality E.  */
 
 
void
void
omega_negate_geq (omega_pb pb, int e)
omega_negate_geq (omega_pb pb, int e)
{
{
  int i;
  int i;
 
 
  for (i = pb->num_vars; i >= 0; i--)
  for (i = pb->num_vars; i >= 0; i--)
    pb->geqs[e].coef[i] *= -1;
    pb->geqs[e].coef[i] *= -1;
 
 
  pb->geqs[e].coef[0]--;
  pb->geqs[e].coef[0]--;
  pb->geqs[e].touched = 1;
  pb->geqs[e].touched = 1;
}
}
 
 
/* Returns OMEGA_TRUE when problem PB has a solution.  */
/* Returns OMEGA_TRUE when problem PB has a solution.  */
 
 
static enum omega_result
static enum omega_result
verify_omega_pb (omega_pb pb)
verify_omega_pb (omega_pb pb)
{
{
  enum omega_result result;
  enum omega_result result;
  int e;
  int e;
  bool any_color = false;
  bool any_color = false;
  omega_pb tmp_problem = XNEW (struct omega_pb_d);
  omega_pb tmp_problem = XNEW (struct omega_pb_d);
 
 
  omega_copy_problem (tmp_problem, pb);
  omega_copy_problem (tmp_problem, pb);
  tmp_problem->safe_vars = 0;
  tmp_problem->safe_vars = 0;
  tmp_problem->num_subs = 0;
  tmp_problem->num_subs = 0;
 
 
  for (e = pb->num_geqs - 1; e >= 0; e--)
  for (e = pb->num_geqs - 1; e >= 0; e--)
    if (pb->geqs[e].color == omega_red)
    if (pb->geqs[e].color == omega_red)
      {
      {
        any_color = true;
        any_color = true;
        break;
        break;
      }
      }
 
 
  if (please_no_equalities_in_simplified_problems)
  if (please_no_equalities_in_simplified_problems)
    any_color = true;
    any_color = true;
 
 
  if (any_color)
  if (any_color)
    original_problem = no_problem;
    original_problem = no_problem;
  else
  else
    original_problem = pb;
    original_problem = pb;
 
 
  if (dump_file && (dump_flags & TDF_DETAILS))
  if (dump_file && (dump_flags & TDF_DETAILS))
    {
    {
      fprintf (dump_file, "verifying problem");
      fprintf (dump_file, "verifying problem");
 
 
      if (any_color)
      if (any_color)
        fprintf (dump_file, " (color mode)");
        fprintf (dump_file, " (color mode)");
 
 
      fprintf (dump_file, " :\n");
      fprintf (dump_file, " :\n");
      omega_print_problem (dump_file, pb);
      omega_print_problem (dump_file, pb);
    }
    }
 
 
  result = omega_solve_problem (tmp_problem, omega_unknown);
  result = omega_solve_problem (tmp_problem, omega_unknown);
  original_problem = no_problem;
  original_problem = no_problem;
  free (tmp_problem);
  free (tmp_problem);
 
 
  if (dump_file && (dump_flags & TDF_DETAILS))
  if (dump_file && (dump_flags & TDF_DETAILS))
    {
    {
      if (result != omega_false)
      if (result != omega_false)
        fprintf (dump_file, "verified problem\n");
        fprintf (dump_file, "verified problem\n");
      else
      else
        fprintf (dump_file, "disproved problem\n");
        fprintf (dump_file, "disproved problem\n");
      omega_print_problem (dump_file, pb);
      omega_print_problem (dump_file, pb);
    }
    }
 
 
  return result;
  return result;
}
}
 
 
/* Add a new equality to problem PB at last position E.  */
/* Add a new equality to problem PB at last position E.  */
 
 
static void
static void
adding_equality_constraint (omega_pb pb, int e)
adding_equality_constraint (omega_pb pb, int e)
{
{
  if (original_problem != no_problem
  if (original_problem != no_problem
      && original_problem != pb
      && original_problem != pb
      && !conservative)
      && !conservative)
    {
    {
      int i, j;
      int i, j;
      int e2 = original_problem->num_eqs++;
      int e2 = original_problem->num_eqs++;
 
 
      if (dump_file && (dump_flags & TDF_DETAILS))
      if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file,
        fprintf (dump_file,
                 "adding equality constraint %d to outer problem\n", e2);
                 "adding equality constraint %d to outer problem\n", e2);
      omega_init_eqn_zero (&original_problem->eqs[e2],
      omega_init_eqn_zero (&original_problem->eqs[e2],
                           original_problem->num_vars);
                           original_problem->num_vars);
 
 
      for (i = pb->num_vars; i >= 1; i--)
      for (i = pb->num_vars; i >= 1; i--)
        {
        {
          for (j = original_problem->num_vars; j >= 1; j--)
          for (j = original_problem->num_vars; j >= 1; j--)
            if (original_problem->var[j] == pb->var[i])
            if (original_problem->var[j] == pb->var[i])
              break;
              break;
 
 
          if (j <= 0)
          if (j <= 0)
            {
            {
              if (dump_file && (dump_flags & TDF_DETAILS))
              if (dump_file && (dump_flags & TDF_DETAILS))
                fprintf (dump_file, "retracting\n");
                fprintf (dump_file, "retracting\n");
              original_problem->num_eqs--;
              original_problem->num_eqs--;
              return;
              return;
            }
            }
          original_problem->eqs[e2].coef[j] = pb->eqs[e].coef[i];
          original_problem->eqs[e2].coef[j] = pb->eqs[e].coef[i];
        }
        }
 
 
      original_problem->eqs[e2].coef[0] = pb->eqs[e].coef[0];
      original_problem->eqs[e2].coef[0] = pb->eqs[e].coef[0];
 
 
      if (dump_file && (dump_flags & TDF_DETAILS))
      if (dump_file && (dump_flags & TDF_DETAILS))
        omega_print_problem (dump_file, original_problem);
        omega_print_problem (dump_file, original_problem);
    }
    }
}
}
 
 
static int *fast_lookup;
static int *fast_lookup;
static int *fast_lookup_red;
static int *fast_lookup_red;
 
 
typedef enum {
typedef enum {
  normalize_false,
  normalize_false,
  normalize_uncoupled,
  normalize_uncoupled,
  normalize_coupled
  normalize_coupled
} normalize_return_type;
} normalize_return_type;
 
 
/* Normalizes PB by removing redundant constraints.  Returns
/* Normalizes PB by removing redundant constraints.  Returns
   normalize_false when the constraints system has no solution,
   normalize_false when the constraints system has no solution,
   otherwise returns normalize_coupled or normalize_uncoupled.  */
   otherwise returns normalize_coupled or normalize_uncoupled.  */
 
 
static normalize_return_type
static normalize_return_type
normalize_omega_problem (omega_pb pb)
normalize_omega_problem (omega_pb pb)
{
{
  int e, i, j, k, n_vars;
  int e, i, j, k, n_vars;
  int coupled_subscripts = 0;
  int coupled_subscripts = 0;
 
 
  n_vars = pb->num_vars;
  n_vars = pb->num_vars;
 
 
  for (e = 0; e < pb->num_geqs; e++)
  for (e = 0; e < pb->num_geqs; e++)
    {
    {
      if (!pb->geqs[e].touched)
      if (!pb->geqs[e].touched)
        {
        {
          if (!single_var_geq (&pb->geqs[e], n_vars))
          if (!single_var_geq (&pb->geqs[e], n_vars))
            coupled_subscripts = 1;
            coupled_subscripts = 1;
        }
        }
      else
      else
        {
        {
          int g, top_var, i0, hashCode;
          int g, top_var, i0, hashCode;
          int *p = &packing[0];
          int *p = &packing[0];
 
 
          for (k = 1; k <= n_vars; k++)
          for (k = 1; k <= n_vars; k++)
            if (pb->geqs[e].coef[k])
            if (pb->geqs[e].coef[k])
              *(p++) = k;
              *(p++) = k;
 
 
          top_var = (p - &packing[0]) - 1;
          top_var = (p - &packing[0]) - 1;
 
 
          if (top_var == -1)
          if (top_var == -1)
            {
            {
              if (pb->geqs[e].coef[0] < 0)
              if (pb->geqs[e].coef[0] < 0)
                {
                {
                  if (dump_file && (dump_flags & TDF_DETAILS))
                  if (dump_file && (dump_flags & TDF_DETAILS))
                    {
                    {
                      omega_print_geq (dump_file, pb, &pb->geqs[e]);
                      omega_print_geq (dump_file, pb, &pb->geqs[e]);
                      fprintf (dump_file, "\nequations have no solution \n");
                      fprintf (dump_file, "\nequations have no solution \n");
                    }
                    }
                  return normalize_false;
                  return normalize_false;
                }
                }
 
 
              omega_delete_geq (pb, e, n_vars);
              omega_delete_geq (pb, e, n_vars);
              e--;
              e--;
              continue;
              continue;
            }
            }
          else if (top_var == 0)
          else if (top_var == 0)
            {
            {
              int singlevar = packing[0];
              int singlevar = packing[0];
 
 
              g = pb->geqs[e].coef[singlevar];
              g = pb->geqs[e].coef[singlevar];
 
 
              if (g > 0)
              if (g > 0)
                {
                {
                  pb->geqs[e].coef[singlevar] = 1;
                  pb->geqs[e].coef[singlevar] = 1;
                  pb->geqs[e].key = singlevar;
                  pb->geqs[e].key = singlevar;
                }
                }
              else
              else
                {
                {
                  g = -g;
                  g = -g;
                  pb->geqs[e].coef[singlevar] = -1;
                  pb->geqs[e].coef[singlevar] = -1;
                  pb->geqs[e].key = -singlevar;
                  pb->geqs[e].key = -singlevar;
                }
                }
 
 
              if (g > 1)
              if (g > 1)
                pb->geqs[e].coef[0] = int_div (pb->geqs[e].coef[0], g);
                pb->geqs[e].coef[0] = int_div (pb->geqs[e].coef[0], g);
            }
            }
          else
          else
            {
            {
              int g2;
              int g2;
              int hash_key_multiplier = 31;
              int hash_key_multiplier = 31;
 
 
              coupled_subscripts = 1;
              coupled_subscripts = 1;
              i0 = top_var;
              i0 = top_var;
              i = packing[i0--];
              i = packing[i0--];
              g = pb->geqs[e].coef[i];
              g = pb->geqs[e].coef[i];
              hashCode = g * (i + 3);
              hashCode = g * (i + 3);
 
 
              if (g < 0)
              if (g < 0)
                g = -g;
                g = -g;
 
 
              for (; i0 >= 0; i0--)
              for (; i0 >= 0; i0--)
                {
                {
                  int x;
                  int x;
 
 
                  i = packing[i0];
                  i = packing[i0];
                  x = pb->geqs[e].coef[i];
                  x = pb->geqs[e].coef[i];
                  hashCode = hashCode * hash_key_multiplier * (i + 3) + x;
                  hashCode = hashCode * hash_key_multiplier * (i + 3) + x;
 
 
                  if (x < 0)
                  if (x < 0)
                    x = -x;
                    x = -x;
 
 
                  if (x == 1)
                  if (x == 1)
                    {
                    {
                      g = 1;
                      g = 1;
                      i0--;
                      i0--;
                      break;
                      break;
                    }
                    }
                  else
                  else
                    g = gcd (x, g);
                    g = gcd (x, g);
                }
                }
 
 
              for (; i0 >= 0; i0--)
              for (; i0 >= 0; i0--)
                {
                {
                  int x;
                  int x;
                  i = packing[i0];
                  i = packing[i0];
                  x = pb->geqs[e].coef[i];
                  x = pb->geqs[e].coef[i];
                  hashCode = hashCode * hash_key_multiplier * (i + 3) + x;
                  hashCode = hashCode * hash_key_multiplier * (i + 3) + x;
                }
                }
 
 
              if (g > 1)
              if (g > 1)
                {
                {
                  pb->geqs[e].coef[0] = int_div (pb->geqs[e].coef[0], g);
                  pb->geqs[e].coef[0] = int_div (pb->geqs[e].coef[0], g);
                  i0 = top_var;
                  i0 = top_var;
                  i = packing[i0--];
                  i = packing[i0--];
                  pb->geqs[e].coef[i] = pb->geqs[e].coef[i] / g;
                  pb->geqs[e].coef[i] = pb->geqs[e].coef[i] / g;
                  hashCode = pb->geqs[e].coef[i] * (i + 3);
                  hashCode = pb->geqs[e].coef[i] * (i + 3);
 
 
                  for (; i0 >= 0; i0--)
                  for (; i0 >= 0; i0--)
                    {
                    {
                      i = packing[i0];
                      i = packing[i0];
                      pb->geqs[e].coef[i] = pb->geqs[e].coef[i] / g;
                      pb->geqs[e].coef[i] = pb->geqs[e].coef[i] / g;
                      hashCode = hashCode * hash_key_multiplier * (i + 3)
                      hashCode = hashCode * hash_key_multiplier * (i + 3)
                        + pb->geqs[e].coef[i];
                        + pb->geqs[e].coef[i];
                    }
                    }
                }
                }
 
 
              g2 = abs (hashCode);
              g2 = abs (hashCode);
 
 
              if (dump_file && (dump_flags & TDF_DETAILS))
              if (dump_file && (dump_flags & TDF_DETAILS))
                {
                {
                  fprintf (dump_file, "Hash code = %d, eqn = ", hashCode);
                  fprintf (dump_file, "Hash code = %d, eqn = ", hashCode);
                  omega_print_geq (dump_file, pb, &pb->geqs[e]);
                  omega_print_geq (dump_file, pb, &pb->geqs[e]);
                  fprintf (dump_file, "\n");
                  fprintf (dump_file, "\n");
                }
                }
 
 
              j = g2 % HASH_TABLE_SIZE;
              j = g2 % HASH_TABLE_SIZE;
 
 
              do {
              do {
                eqn proto = &(hash_master[j]);
                eqn proto = &(hash_master[j]);
 
 
                if (proto->touched == g2)
                if (proto->touched == g2)
                  {
                  {
                    if (proto->coef[0] == top_var)
                    if (proto->coef[0] == top_var)
                      {
                      {
                        if (hashCode >= 0)
                        if (hashCode >= 0)
                          for (i0 = top_var; i0 >= 0; i0--)
                          for (i0 = top_var; i0 >= 0; i0--)
                            {
                            {
                              i = packing[i0];
                              i = packing[i0];
 
 
                              if (pb->geqs[e].coef[i] != proto->coef[i])
                              if (pb->geqs[e].coef[i] != proto->coef[i])
                                break;
                                break;
                            }
                            }
                        else
                        else
                          for (i0 = top_var; i0 >= 0; i0--)
                          for (i0 = top_var; i0 >= 0; i0--)
                            {
                            {
                              i = packing[i0];
                              i = packing[i0];
 
 
                              if (pb->geqs[e].coef[i] != -proto->coef[i])
                              if (pb->geqs[e].coef[i] != -proto->coef[i])
                                break;
                                break;
                            }
                            }
 
 
                        if (i0 < 0)
                        if (i0 < 0)
                          {
                          {
                            if (hashCode >= 0)
                            if (hashCode >= 0)
                              pb->geqs[e].key = proto->key;
                              pb->geqs[e].key = proto->key;
                            else
                            else
                              pb->geqs[e].key = -proto->key;
                              pb->geqs[e].key = -proto->key;
                            break;
                            break;
                          }
                          }
                      }
                      }
                  }
                  }
                else if (proto->touched < 0)
                else if (proto->touched < 0)
                  {
                  {
                    omega_init_eqn_zero (proto, pb->num_vars);
                    omega_init_eqn_zero (proto, pb->num_vars);
                    if (hashCode >= 0)
                    if (hashCode >= 0)
                      for (i0 = top_var; i0 >= 0; i0--)
                      for (i0 = top_var; i0 >= 0; i0--)
                        {
                        {
                          i = packing[i0];
                          i = packing[i0];
                          proto->coef[i] = pb->geqs[e].coef[i];
                          proto->coef[i] = pb->geqs[e].coef[i];
                        }
                        }
                    else
                    else
                      for (i0 = top_var; i0 >= 0; i0--)
                      for (i0 = top_var; i0 >= 0; i0--)
                        {
                        {
                          i = packing[i0];
                          i = packing[i0];
                          proto->coef[i] = -pb->geqs[e].coef[i];
                          proto->coef[i] = -pb->geqs[e].coef[i];
                        }
                        }
 
 
                    proto->coef[0] = top_var;
                    proto->coef[0] = top_var;
                    proto->touched = g2;
                    proto->touched = g2;
 
 
                    if (dump_file && (dump_flags & TDF_DETAILS))
                    if (dump_file && (dump_flags & TDF_DETAILS))
                      fprintf (dump_file, " constraint key = %d\n",
                      fprintf (dump_file, " constraint key = %d\n",
                               next_key);
                               next_key);
 
 
                    proto->key = next_key++;
                    proto->key = next_key++;
 
 
                    /* Too many hash keys generated.  */
                    /* Too many hash keys generated.  */
                    gcc_assert (proto->key <= MAX_KEYS);
                    gcc_assert (proto->key <= MAX_KEYS);
 
 
                    if (hashCode >= 0)
                    if (hashCode >= 0)
                      pb->geqs[e].key = proto->key;
                      pb->geqs[e].key = proto->key;
                    else
                    else
                      pb->geqs[e].key = -proto->key;
                      pb->geqs[e].key = -proto->key;
 
 
                    break;
                    break;
                  }
                  }
 
 
                j = (j + 1) % HASH_TABLE_SIZE;
                j = (j + 1) % HASH_TABLE_SIZE;
              } while (1);
              } while (1);
            }
            }
 
 
          pb->geqs[e].touched = 0;
          pb->geqs[e].touched = 0;
        }
        }
 
 
      {
      {
        int eKey = pb->geqs[e].key;
        int eKey = pb->geqs[e].key;
        int e2;
        int e2;
        if (e > 0)
        if (e > 0)
          {
          {
            int cTerm = pb->geqs[e].coef[0];
            int cTerm = pb->geqs[e].coef[0];
            e2 = fast_lookup[MAX_KEYS - eKey];
            e2 = fast_lookup[MAX_KEYS - eKey];
 
 
            if (e2 < e && pb->geqs[e2].key == -eKey
            if (e2 < e && pb->geqs[e2].key == -eKey
                && pb->geqs[e2].color == omega_black)
                && pb->geqs[e2].color == omega_black)
              {
              {
                if (pb->geqs[e2].coef[0] < -cTerm)
                if (pb->geqs[e2].coef[0] < -cTerm)
                  {
                  {
                    if (dump_file && (dump_flags & TDF_DETAILS))
                    if (dump_file && (dump_flags & TDF_DETAILS))
                      {
                      {
                        omega_print_geq (dump_file, pb, &pb->geqs[e]);
                        omega_print_geq (dump_file, pb, &pb->geqs[e]);
                        fprintf (dump_file, "\n");
                        fprintf (dump_file, "\n");
                        omega_print_geq (dump_file, pb, &pb->geqs[e2]);
                        omega_print_geq (dump_file, pb, &pb->geqs[e2]);
                        fprintf (dump_file,
                        fprintf (dump_file,
                                 "\nequations have no solution \n");
                                 "\nequations have no solution \n");
                      }
                      }
                    return normalize_false;
                    return normalize_false;
                  }
                  }
 
 
                if (pb->geqs[e2].coef[0] == -cTerm
                if (pb->geqs[e2].coef[0] == -cTerm
                    && (create_color
                    && (create_color
                        || pb->geqs[e].color == omega_black))
                        || pb->geqs[e].color == omega_black))
                  {
                  {
                    omega_copy_eqn (&pb->eqs[pb->num_eqs], &pb->geqs[e],
                    omega_copy_eqn (&pb->eqs[pb->num_eqs], &pb->geqs[e],
                                    pb->num_vars);
                                    pb->num_vars);
                    if (pb->geqs[e].color == omega_black)
                    if (pb->geqs[e].color == omega_black)
                      adding_equality_constraint (pb, pb->num_eqs);
                      adding_equality_constraint (pb, pb->num_eqs);
                    pb->num_eqs++;
                    pb->num_eqs++;
                    gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
                    gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
                  }
                  }
              }
              }
 
 
            e2 = fast_lookup_red[MAX_KEYS - eKey];
            e2 = fast_lookup_red[MAX_KEYS - eKey];
 
 
            if (e2 < e && pb->geqs[e2].key == -eKey
            if (e2 < e && pb->geqs[e2].key == -eKey
                && pb->geqs[e2].color == omega_red)
                && pb->geqs[e2].color == omega_red)
              {
              {
                if (pb->geqs[e2].coef[0] < -cTerm)
                if (pb->geqs[e2].coef[0] < -cTerm)
                  {
                  {
                    if (dump_file && (dump_flags & TDF_DETAILS))
                    if (dump_file && (dump_flags & TDF_DETAILS))
                      {
                      {
                        omega_print_geq (dump_file, pb, &pb->geqs[e]);
                        omega_print_geq (dump_file, pb, &pb->geqs[e]);
                        fprintf (dump_file, "\n");
                        fprintf (dump_file, "\n");
                        omega_print_geq (dump_file, pb, &pb->geqs[e2]);
                        omega_print_geq (dump_file, pb, &pb->geqs[e2]);
                        fprintf (dump_file,
                        fprintf (dump_file,
                                 "\nequations have no solution \n");
                                 "\nequations have no solution \n");
                      }
                      }
                    return normalize_false;
                    return normalize_false;
                  }
                  }
 
 
                if (pb->geqs[e2].coef[0] == -cTerm && create_color)
                if (pb->geqs[e2].coef[0] == -cTerm && create_color)
                  {
                  {
                    omega_copy_eqn (&pb->eqs[pb->num_eqs], &pb->geqs[e],
                    omega_copy_eqn (&pb->eqs[pb->num_eqs], &pb->geqs[e],
                                    pb->num_vars);
                                    pb->num_vars);
                    pb->eqs[pb->num_eqs].color = omega_red;
                    pb->eqs[pb->num_eqs].color = omega_red;
                    pb->num_eqs++;
                    pb->num_eqs++;
                    gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
                    gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
                  }
                  }
              }
              }
 
 
            e2 = fast_lookup[MAX_KEYS + eKey];
            e2 = fast_lookup[MAX_KEYS + eKey];
 
 
            if (e2 < e && pb->geqs[e2].key == eKey
            if (e2 < e && pb->geqs[e2].key == eKey
                && pb->geqs[e2].color == omega_black)
                && pb->geqs[e2].color == omega_black)
              {
              {
                if (pb->geqs[e2].coef[0] > cTerm)
                if (pb->geqs[e2].coef[0] > cTerm)
                  {
                  {
                    if (pb->geqs[e].color == omega_black)
                    if (pb->geqs[e].color == omega_black)
                      {
                      {
                        if (dump_file && (dump_flags & TDF_DETAILS))
                        if (dump_file && (dump_flags & TDF_DETAILS))
                          {
                          {
                            fprintf (dump_file,
                            fprintf (dump_file,
                                     "Removing Redundant Equation: ");
                                     "Removing Redundant Equation: ");
                            omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
                            omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
                            fprintf (dump_file, "\n");
                            fprintf (dump_file, "\n");
                            fprintf (dump_file,
                            fprintf (dump_file,
                                     "[a]      Made Redundant by: ");
                                     "[a]      Made Redundant by: ");
                            omega_print_geq (dump_file, pb, &(pb->geqs[e]));
                            omega_print_geq (dump_file, pb, &(pb->geqs[e]));
                            fprintf (dump_file, "\n");
                            fprintf (dump_file, "\n");
                          }
                          }
                        pb->geqs[e2].coef[0] = cTerm;
                        pb->geqs[e2].coef[0] = cTerm;
                        omega_delete_geq (pb, e, n_vars);
                        omega_delete_geq (pb, e, n_vars);
                        e--;
                        e--;
                        continue;
                        continue;
                      }
                      }
                  }
                  }
                else
                else
                  {
                  {
                    if (dump_file && (dump_flags & TDF_DETAILS))
                    if (dump_file && (dump_flags & TDF_DETAILS))
                      {
                      {
                        fprintf (dump_file, "Removing Redundant Equation: ");
                        fprintf (dump_file, "Removing Redundant Equation: ");
                        omega_print_geq (dump_file, pb, &(pb->geqs[e]));
                        omega_print_geq (dump_file, pb, &(pb->geqs[e]));
                        fprintf (dump_file, "\n");
                        fprintf (dump_file, "\n");
                        fprintf (dump_file, "[b]      Made Redundant by: ");
                        fprintf (dump_file, "[b]      Made Redundant by: ");
                        omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
                        omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
                        fprintf (dump_file, "\n");
                        fprintf (dump_file, "\n");
                      }
                      }
                    omega_delete_geq (pb, e, n_vars);
                    omega_delete_geq (pb, e, n_vars);
                    e--;
                    e--;
                    continue;
                    continue;
                  }
                  }
              }
              }
 
 
            e2 = fast_lookup_red[MAX_KEYS + eKey];
            e2 = fast_lookup_red[MAX_KEYS + eKey];
 
 
            if (e2 < e && pb->geqs[e2].key == eKey
            if (e2 < e && pb->geqs[e2].key == eKey
                && pb->geqs[e2].color == omega_red)
                && pb->geqs[e2].color == omega_red)
              {
              {
                if (pb->geqs[e2].coef[0] >= cTerm)
                if (pb->geqs[e2].coef[0] >= cTerm)
                  {
                  {
                    if (dump_file && (dump_flags & TDF_DETAILS))
                    if (dump_file && (dump_flags & TDF_DETAILS))
                      {
                      {
                        fprintf (dump_file, "Removing Redundant Equation: ");
                        fprintf (dump_file, "Removing Redundant Equation: ");
                        omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
                        omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
                        fprintf (dump_file, "\n");
                        fprintf (dump_file, "\n");
                        fprintf (dump_file, "[c]      Made Redundant by: ");
                        fprintf (dump_file, "[c]      Made Redundant by: ");
                        omega_print_geq (dump_file, pb, &(pb->geqs[e]));
                        omega_print_geq (dump_file, pb, &(pb->geqs[e]));
                        fprintf (dump_file, "\n");
                        fprintf (dump_file, "\n");
                      }
                      }
                    pb->geqs[e2].coef[0] = cTerm;
                    pb->geqs[e2].coef[0] = cTerm;
                    pb->geqs[e2].color = pb->geqs[e].color;
                    pb->geqs[e2].color = pb->geqs[e].color;
                  }
                  }
                else if (pb->geqs[e].color == omega_red)
                else if (pb->geqs[e].color == omega_red)
                  {
                  {
                    if (dump_file && (dump_flags & TDF_DETAILS))
                    if (dump_file && (dump_flags & TDF_DETAILS))
                      {
                      {
                        fprintf (dump_file, "Removing Redundant Equation: ");
                        fprintf (dump_file, "Removing Redundant Equation: ");
                        omega_print_geq (dump_file, pb, &(pb->geqs[e]));
                        omega_print_geq (dump_file, pb, &(pb->geqs[e]));
                        fprintf (dump_file, "\n");
                        fprintf (dump_file, "\n");
                        fprintf (dump_file, "[d]      Made Redundant by: ");
                        fprintf (dump_file, "[d]      Made Redundant by: ");
                        omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
                        omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
                        fprintf (dump_file, "\n");
                        fprintf (dump_file, "\n");
                      }
                      }
                  }
                  }
                omega_delete_geq (pb, e, n_vars);
                omega_delete_geq (pb, e, n_vars);
                e--;
                e--;
                continue;
                continue;
 
 
              }
              }
          }
          }
 
 
        if (pb->geqs[e].color == omega_red)
        if (pb->geqs[e].color == omega_red)
          fast_lookup_red[MAX_KEYS + eKey] = e;
          fast_lookup_red[MAX_KEYS + eKey] = e;
        else
        else
          fast_lookup[MAX_KEYS + eKey] = e;
          fast_lookup[MAX_KEYS + eKey] = e;
      }
      }
    }
    }
 
 
  create_color = false;
  create_color = false;
  return coupled_subscripts ? normalize_coupled : normalize_uncoupled;
  return coupled_subscripts ? normalize_coupled : normalize_uncoupled;
}
}
 
 
/* Divide the coefficients of EQN by their gcd.  N_VARS is the number
/* Divide the coefficients of EQN by their gcd.  N_VARS is the number
   of variables in EQN.  */
   of variables in EQN.  */
 
 
static inline void
static inline void
divide_eqn_by_gcd (eqn eqn, int n_vars)
divide_eqn_by_gcd (eqn eqn, int n_vars)
{
{
  int var, g = 0;
  int var, g = 0;
 
 
  for (var = n_vars; var >= 0; var--)
  for (var = n_vars; var >= 0; var--)
    g = gcd (abs (eqn->coef[var]), g);
    g = gcd (abs (eqn->coef[var]), g);
 
 
  if (g)
  if (g)
    for (var = n_vars; var >= 0; var--)
    for (var = n_vars; var >= 0; var--)
      eqn->coef[var] = eqn->coef[var] / g;
      eqn->coef[var] = eqn->coef[var] / g;
}
}
 
 
/* Rewrite some non-safe variables in function of protected
/* Rewrite some non-safe variables in function of protected
   wildcard variables.  */
   wildcard variables.  */
 
 
static void
static void
cleanout_wildcards (omega_pb pb)
cleanout_wildcards (omega_pb pb)
{
{
  int e, i, j;
  int e, i, j;
  int n_vars = pb->num_vars;
  int n_vars = pb->num_vars;
  bool renormalize = false;
  bool renormalize = false;
 
 
  for (e = pb->num_eqs - 1; e >= 0; e--)
  for (e = pb->num_eqs - 1; e >= 0; e--)
    for (i = n_vars; !omega_safe_var_p (pb, i); i--)
    for (i = n_vars; !omega_safe_var_p (pb, i); i--)
      if (pb->eqs[e].coef[i] != 0)
      if (pb->eqs[e].coef[i] != 0)
        {
        {
          /* i is the last nonzero non-safe variable.  */
          /* i is the last nonzero non-safe variable.  */
 
 
          for (j = i - 1; !omega_safe_var_p (pb, j); j--)
          for (j = i - 1; !omega_safe_var_p (pb, j); j--)
            if (pb->eqs[e].coef[j] != 0)
            if (pb->eqs[e].coef[j] != 0)
              break;
              break;
 
 
          /* j is the next nonzero non-safe variable, or points
          /* j is the next nonzero non-safe variable, or points
             to a safe variable: it is then a wildcard variable.  */
             to a safe variable: it is then a wildcard variable.  */
 
 
          /* Clean it out.  */
          /* Clean it out.  */
          if (omega_safe_var_p (pb, j))
          if (omega_safe_var_p (pb, j))
            {
            {
              eqn sub = &(pb->eqs[e]);
              eqn sub = &(pb->eqs[e]);
              int c = pb->eqs[e].coef[i];
              int c = pb->eqs[e].coef[i];
              int a = abs (c);
              int a = abs (c);
              int e2;
              int e2;
 
 
              if (dump_file && (dump_flags & TDF_DETAILS))
              if (dump_file && (dump_flags & TDF_DETAILS))
                {
                {
                  fprintf (dump_file,
                  fprintf (dump_file,
                           "Found a single wild card equality: ");
                           "Found a single wild card equality: ");
                  omega_print_eq (dump_file, pb, &pb->eqs[e]);
                  omega_print_eq (dump_file, pb, &pb->eqs[e]);
                  fprintf (dump_file, "\n");
                  fprintf (dump_file, "\n");
                  omega_print_problem (dump_file, pb);
                  omega_print_problem (dump_file, pb);
                }
                }
 
 
              for (e2 = pb->num_eqs - 1; e2 >= 0; e2--)
              for (e2 = pb->num_eqs - 1; e2 >= 0; e2--)
                if (e != e2 && pb->eqs[e2].coef[i]
                if (e != e2 && pb->eqs[e2].coef[i]
                    && (pb->eqs[e2].color == omega_red
                    && (pb->eqs[e2].color == omega_red
                        || (pb->eqs[e2].color == omega_black
                        || (pb->eqs[e2].color == omega_black
                            && pb->eqs[e].color == omega_black)))
                            && pb->eqs[e].color == omega_black)))
                  {
                  {
                    eqn eqn = &(pb->eqs[e2]);
                    eqn eqn = &(pb->eqs[e2]);
                    int var, k;
                    int var, k;
 
 
                    for (var = n_vars; var >= 0; var--)
                    for (var = n_vars; var >= 0; var--)
                      eqn->coef[var] *= a;
                      eqn->coef[var] *= a;
 
 
                    k = eqn->coef[i];
                    k = eqn->coef[i];
 
 
                    for (var = n_vars; var >= 0; var--)
                    for (var = n_vars; var >= 0; var--)
                      eqn->coef[var] -= sub->coef[var] * k / c;
                      eqn->coef[var] -= sub->coef[var] * k / c;
 
 
                    eqn->coef[i] = 0;
                    eqn->coef[i] = 0;
                    divide_eqn_by_gcd (eqn, n_vars);
                    divide_eqn_by_gcd (eqn, n_vars);
                  }
                  }
 
 
              for (e2 = pb->num_geqs - 1; e2 >= 0; e2--)
              for (e2 = pb->num_geqs - 1; e2 >= 0; e2--)
                if (pb->geqs[e2].coef[i]
                if (pb->geqs[e2].coef[i]
                    && (pb->geqs[e2].color == omega_red
                    && (pb->geqs[e2].color == omega_red
                        || (pb->eqs[e].color == omega_black
                        || (pb->eqs[e].color == omega_black
                            && pb->geqs[e2].color == omega_black)))
                            && pb->geqs[e2].color == omega_black)))
                  {
                  {
                    eqn eqn = &(pb->geqs[e2]);
                    eqn eqn = &(pb->geqs[e2]);
                    int var, k;
                    int var, k;
 
 
                    for (var = n_vars; var >= 0; var--)
                    for (var = n_vars; var >= 0; var--)
                      eqn->coef[var] *= a;
                      eqn->coef[var] *= a;
 
 
                    k = eqn->coef[i];
                    k = eqn->coef[i];
 
 
                    for (var = n_vars; var >= 0; var--)
                    for (var = n_vars; var >= 0; var--)
                      eqn->coef[var] -= sub->coef[var] * k / c;
                      eqn->coef[var] -= sub->coef[var] * k / c;
 
 
                    eqn->coef[i] = 0;
                    eqn->coef[i] = 0;
                    eqn->touched = 1;
                    eqn->touched = 1;
                    renormalize = true;
                    renormalize = true;
                  }
                  }
 
 
              for (e2 = pb->num_subs - 1; e2 >= 0; e2--)
              for (e2 = pb->num_subs - 1; e2 >= 0; e2--)
                if (pb->subs[e2].coef[i]
                if (pb->subs[e2].coef[i]
                    && (pb->subs[e2].color == omega_red
                    && (pb->subs[e2].color == omega_red
                        || (pb->subs[e2].color == omega_black
                        || (pb->subs[e2].color == omega_black
                            && pb->eqs[e].color == omega_black)))
                            && pb->eqs[e].color == omega_black)))
                  {
                  {
                    eqn eqn = &(pb->subs[e2]);
                    eqn eqn = &(pb->subs[e2]);
                    int var, k;
                    int var, k;
 
 
                    for (var = n_vars; var >= 0; var--)
                    for (var = n_vars; var >= 0; var--)
                      eqn->coef[var] *= a;
                      eqn->coef[var] *= a;
 
 
                    k = eqn->coef[i];
                    k = eqn->coef[i];
 
 
                    for (var = n_vars; var >= 0; var--)
                    for (var = n_vars; var >= 0; var--)
                      eqn->coef[var] -= sub->coef[var] * k / c;
                      eqn->coef[var] -= sub->coef[var] * k / c;
 
 
                    eqn->coef[i] = 0;
                    eqn->coef[i] = 0;
                    divide_eqn_by_gcd (eqn, n_vars);
                    divide_eqn_by_gcd (eqn, n_vars);
                  }
                  }
 
 
              if (dump_file && (dump_flags & TDF_DETAILS))
              if (dump_file && (dump_flags & TDF_DETAILS))
                {
                {
                  fprintf (dump_file, "cleaned-out wildcard: ");
                  fprintf (dump_file, "cleaned-out wildcard: ");
                  omega_print_problem (dump_file, pb);
                  omega_print_problem (dump_file, pb);
                }
                }
              break;
              break;
            }
            }
        }
        }
 
 
  if (renormalize)
  if (renormalize)
    normalize_omega_problem (pb);
    normalize_omega_problem (pb);
}
}
 
 
/* Swap values contained in I and J.  */
/* Swap values contained in I and J.  */
 
 
static inline void
static inline void
swap (int *i, int *j)
swap (int *i, int *j)
{
{
  int tmp;
  int tmp;
  tmp = *i;
  tmp = *i;
  *i = *j;
  *i = *j;
  *j = tmp;
  *j = tmp;
}
}
 
 
/* Swap values contained in I and J.  */
/* Swap values contained in I and J.  */
 
 
static inline void
static inline void
bswap (bool *i, bool *j)
bswap (bool *i, bool *j)
{
{
  bool tmp;
  bool tmp;
  tmp = *i;
  tmp = *i;
  *i = *j;
  *i = *j;
  *j = tmp;
  *j = tmp;
}
}
 
 
/* Make variable IDX unprotected in PB, by swapping its index at the
/* Make variable IDX unprotected in PB, by swapping its index at the
   PB->safe_vars rank.  */
   PB->safe_vars rank.  */
 
 
static inline void
static inline void
omega_unprotect_1 (omega_pb pb, int *idx, bool *unprotect)
omega_unprotect_1 (omega_pb pb, int *idx, bool *unprotect)
{
{
  /* If IDX is protected...  */
  /* If IDX is protected...  */
  if (*idx < pb->safe_vars)
  if (*idx < pb->safe_vars)
    {
    {
      /* ... swap its index with the last non protected index.  */
      /* ... swap its index with the last non protected index.  */
      int j = pb->safe_vars;
      int j = pb->safe_vars;
      int e;
      int e;
 
 
      for (e = pb->num_geqs - 1; e >= 0; e--)
      for (e = pb->num_geqs - 1; e >= 0; e--)
        {
        {
          pb->geqs[e].touched = 1;
          pb->geqs[e].touched = 1;
          swap (&pb->geqs[e].coef[*idx], &pb->geqs[e].coef[j]);
          swap (&pb->geqs[e].coef[*idx], &pb->geqs[e].coef[j]);
        }
        }
 
 
      for (e = pb->num_eqs - 1; e >= 0; e--)
      for (e = pb->num_eqs - 1; e >= 0; e--)
        swap (&pb->eqs[e].coef[*idx], &pb->eqs[e].coef[j]);
        swap (&pb->eqs[e].coef[*idx], &pb->eqs[e].coef[j]);
 
 
      for (e = pb->num_subs - 1; e >= 0; e--)
      for (e = pb->num_subs - 1; e >= 0; e--)
        swap (&pb->subs[e].coef[*idx], &pb->subs[e].coef[j]);
        swap (&pb->subs[e].coef[*idx], &pb->subs[e].coef[j]);
 
 
      if (unprotect)
      if (unprotect)
        bswap (&unprotect[*idx], &unprotect[j]);
        bswap (&unprotect[*idx], &unprotect[j]);
 
 
      swap (&pb->var[*idx], &pb->var[j]);
      swap (&pb->var[*idx], &pb->var[j]);
      pb->forwarding_address[pb->var[*idx]] = *idx;
      pb->forwarding_address[pb->var[*idx]] = *idx;
      pb->forwarding_address[pb->var[j]] = j;
      pb->forwarding_address[pb->var[j]] = j;
      (*idx)--;
      (*idx)--;
    }
    }
 
 
  /* The variable at pb->safe_vars is also unprotected now.  */
  /* The variable at pb->safe_vars is also unprotected now.  */
  pb->safe_vars--;
  pb->safe_vars--;
}
}
 
 
/* During the Fourier-Motzkin elimination some variables are
/* During the Fourier-Motzkin elimination some variables are
   substituted with other variables.  This function resurrects the
   substituted with other variables.  This function resurrects the
   substituted variables in PB.  */
   substituted variables in PB.  */
 
 
static void
static void
resurrect_subs (omega_pb pb)
resurrect_subs (omega_pb pb)
{
{
  if (pb->num_subs > 0
  if (pb->num_subs > 0
      && please_no_equalities_in_simplified_problems == 0)
      && please_no_equalities_in_simplified_problems == 0)
    {
    {
      int i, e, m;
      int i, e, m;
 
 
      if (dump_file && (dump_flags & TDF_DETAILS))
      if (dump_file && (dump_flags & TDF_DETAILS))
        {
        {
          fprintf (dump_file,
          fprintf (dump_file,
                   "problem reduced, bringing variables back to life\n");
                   "problem reduced, bringing variables back to life\n");
          omega_print_problem (dump_file, pb);
          omega_print_problem (dump_file, pb);
        }
        }
 
 
      for (i = 1; omega_safe_var_p (pb, i); i++)
      for (i = 1; omega_safe_var_p (pb, i); i++)
        if (omega_wildcard_p (pb, i))
        if (omega_wildcard_p (pb, i))
          omega_unprotect_1 (pb, &i, NULL);
          omega_unprotect_1 (pb, &i, NULL);
 
 
      m = pb->num_subs;
      m = pb->num_subs;
 
 
      for (e = pb->num_geqs - 1; e >= 0; e--)
      for (e = pb->num_geqs - 1; e >= 0; e--)
        if (single_var_geq (&pb->geqs[e], pb->num_vars))
        if (single_var_geq (&pb->geqs[e], pb->num_vars))
          {
          {
            if (!omega_safe_var_p (pb, abs (pb->geqs[e].key)))
            if (!omega_safe_var_p (pb, abs (pb->geqs[e].key)))
              pb->geqs[e].key += (pb->geqs[e].key > 0 ? m : -m);
              pb->geqs[e].key += (pb->geqs[e].key > 0 ? m : -m);
          }
          }
        else
        else
          {
          {
            pb->geqs[e].touched = 1;
            pb->geqs[e].touched = 1;
            pb->geqs[e].key = 0;
            pb->geqs[e].key = 0;
          }
          }
 
 
      for (i = pb->num_vars; !omega_safe_var_p (pb, i); i--)
      for (i = pb->num_vars; !omega_safe_var_p (pb, i); i--)
        {
        {
          pb->var[i + m] = pb->var[i];
          pb->var[i + m] = pb->var[i];
 
 
          for (e = pb->num_geqs - 1; e >= 0; e--)
          for (e = pb->num_geqs - 1; e >= 0; e--)
            pb->geqs[e].coef[i + m] = pb->geqs[e].coef[i];
            pb->geqs[e].coef[i + m] = pb->geqs[e].coef[i];
 
 
          for (e = pb->num_eqs - 1; e >= 0; e--)
          for (e = pb->num_eqs - 1; e >= 0; e--)
            pb->eqs[e].coef[i + m] = pb->eqs[e].coef[i];
            pb->eqs[e].coef[i + m] = pb->eqs[e].coef[i];
 
 
          for (e = pb->num_subs - 1; e >= 0; e--)
          for (e = pb->num_subs - 1; e >= 0; e--)
            pb->subs[e].coef[i + m] = pb->subs[e].coef[i];
            pb->subs[e].coef[i + m] = pb->subs[e].coef[i];
        }
        }
 
 
      for (i = pb->safe_vars + m; !omega_safe_var_p (pb, i); i--)
      for (i = pb->safe_vars + m; !omega_safe_var_p (pb, i); i--)
        {
        {
          for (e = pb->num_geqs - 1; e >= 0; e--)
          for (e = pb->num_geqs - 1; e >= 0; e--)
            pb->geqs[e].coef[i] = 0;
            pb->geqs[e].coef[i] = 0;
 
 
          for (e = pb->num_eqs - 1; e >= 0; e--)
          for (e = pb->num_eqs - 1; e >= 0; e--)
            pb->eqs[e].coef[i] = 0;
            pb->eqs[e].coef[i] = 0;
 
 
          for (e = pb->num_subs - 1; e >= 0; e--)
          for (e = pb->num_subs - 1; e >= 0; e--)
            pb->subs[e].coef[i] = 0;
            pb->subs[e].coef[i] = 0;
        }
        }
 
 
      pb->num_vars += m;
      pb->num_vars += m;
 
 
      for (e = pb->num_subs - 1; e >= 0; e--)
      for (e = pb->num_subs - 1; e >= 0; e--)
        {
        {
          pb->var[pb->safe_vars + 1 + e] = pb->subs[e].key;
          pb->var[pb->safe_vars + 1 + e] = pb->subs[e].key;
          omega_copy_eqn (&(pb->eqs[pb->num_eqs]), &(pb->subs[e]),
          omega_copy_eqn (&(pb->eqs[pb->num_eqs]), &(pb->subs[e]),
                          pb->num_vars);
                          pb->num_vars);
          pb->eqs[pb->num_eqs].coef[pb->safe_vars + 1 + e] = -1;
          pb->eqs[pb->num_eqs].coef[pb->safe_vars + 1 + e] = -1;
          pb->eqs[pb->num_eqs].color = omega_black;
          pb->eqs[pb->num_eqs].color = omega_black;
 
 
          if (dump_file && (dump_flags & TDF_DETAILS))
          if (dump_file && (dump_flags & TDF_DETAILS))
            {
            {
              fprintf (dump_file, "brought back: ");
              fprintf (dump_file, "brought back: ");
              omega_print_eq (dump_file, pb, &pb->eqs[pb->num_eqs]);
              omega_print_eq (dump_file, pb, &pb->eqs[pb->num_eqs]);
              fprintf (dump_file, "\n");
              fprintf (dump_file, "\n");
            }
            }
 
 
          pb->num_eqs++;
          pb->num_eqs++;
          gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
          gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
        }
        }
 
 
      pb->safe_vars += m;
      pb->safe_vars += m;
      pb->num_subs = 0;
      pb->num_subs = 0;
 
 
      if (dump_file && (dump_flags & TDF_DETAILS))
      if (dump_file && (dump_flags & TDF_DETAILS))
        {
        {
          fprintf (dump_file, "variables brought back to life\n");
          fprintf (dump_file, "variables brought back to life\n");
          omega_print_problem (dump_file, pb);
          omega_print_problem (dump_file, pb);
        }
        }
 
 
      cleanout_wildcards (pb);
      cleanout_wildcards (pb);
    }
    }
}
}
 
 
static inline bool
static inline bool
implies (unsigned int a, unsigned int b)
implies (unsigned int a, unsigned int b)
{
{
  return (a == (a & b));
  return (a == (a & b));
}
}
 
 
/* Eliminate redundant equations in PB.  When EXPENSIVE is true, an
/* Eliminate redundant equations in PB.  When EXPENSIVE is true, an
   extra step is performed.  Returns omega_false when there exist no
   extra step is performed.  Returns omega_false when there exist no
   solution, omega_true otherwise.  */
   solution, omega_true otherwise.  */
 
 
enum omega_result
enum omega_result
omega_eliminate_redundant (omega_pb pb, bool expensive)
omega_eliminate_redundant (omega_pb pb, bool expensive)
{
{
  int c, e, e1, e2, e3, p, q, i, k, alpha, alpha1, alpha2, alpha3;
  int c, e, e1, e2, e3, p, q, i, k, alpha, alpha1, alpha2, alpha3;
  bool *is_dead = XNEWVEC (bool, OMEGA_MAX_GEQS);
  bool *is_dead = XNEWVEC (bool, OMEGA_MAX_GEQS);
  omega_pb tmp_problem;
  omega_pb tmp_problem;
 
 
  /* {P,Z,N}EQS = {Positive,Zero,Negative} Equations.  */
  /* {P,Z,N}EQS = {Positive,Zero,Negative} Equations.  */
  unsigned int *peqs = XNEWVEC (unsigned int, OMEGA_MAX_GEQS);
  unsigned int *peqs = XNEWVEC (unsigned int, OMEGA_MAX_GEQS);
  unsigned int *zeqs = XNEWVEC (unsigned int, OMEGA_MAX_GEQS);
  unsigned int *zeqs = XNEWVEC (unsigned int, OMEGA_MAX_GEQS);
  unsigned int *neqs = XNEWVEC (unsigned int, OMEGA_MAX_GEQS);
  unsigned int *neqs = XNEWVEC (unsigned int, OMEGA_MAX_GEQS);
 
 
  /* PP = Possible Positives, PZ = Possible Zeros, PN = Possible Negatives */
  /* PP = Possible Positives, PZ = Possible Zeros, PN = Possible Negatives */
  unsigned int pp, pz, pn;
  unsigned int pp, pz, pn;
 
 
  if (dump_file && (dump_flags & TDF_DETAILS))
  if (dump_file && (dump_flags & TDF_DETAILS))
    {
    {
      fprintf (dump_file, "in eliminate Redundant:\n");
      fprintf (dump_file, "in eliminate Redundant:\n");
      omega_print_problem (dump_file, pb);
      omega_print_problem (dump_file, pb);
    }
    }
 
 
  for (e = pb->num_geqs - 1; e >= 0; e--)
  for (e = pb->num_geqs - 1; e >= 0; e--)
    {
    {
      int tmp = 1;
      int tmp = 1;
 
 
      is_dead[e] = false;
      is_dead[e] = false;
      peqs[e] = zeqs[e] = neqs[e] = 0;
      peqs[e] = zeqs[e] = neqs[e] = 0;
 
 
      for (i = pb->num_vars; i >= 1; i--)
      for (i = pb->num_vars; i >= 1; i--)
        {
        {
          if (pb->geqs[e].coef[i] > 0)
          if (pb->geqs[e].coef[i] > 0)
            peqs[e] |= tmp;
            peqs[e] |= tmp;
          else if (pb->geqs[e].coef[i] < 0)
          else if (pb->geqs[e].coef[i] < 0)
            neqs[e] |= tmp;
            neqs[e] |= tmp;
          else
          else
            zeqs[e] |= tmp;
            zeqs[e] |= tmp;
 
 
          tmp <<= 1;
          tmp <<= 1;
        }
        }
    }
    }
 
 
 
 
  for (e1 = pb->num_geqs - 1; e1 >= 0; e1--)
  for (e1 = pb->num_geqs - 1; e1 >= 0; e1--)
    if (!is_dead[e1])
    if (!is_dead[e1])
      for (e2 = e1 - 1; e2 >= 0; e2--)
      for (e2 = e1 - 1; e2 >= 0; e2--)
        if (!is_dead[e2])
        if (!is_dead[e2])
          {
          {
            for (p = pb->num_vars; p > 1; p--)
            for (p = pb->num_vars; p > 1; p--)
              for (q = p - 1; q > 0; q--)
              for (q = p - 1; q > 0; q--)
                if ((alpha = pb->geqs[e1].coef[p] * pb->geqs[e2].coef[q]
                if ((alpha = pb->geqs[e1].coef[p] * pb->geqs[e2].coef[q]
                     - pb->geqs[e2].coef[p] * pb->geqs[e1].coef[q]) != 0)
                     - pb->geqs[e2].coef[p] * pb->geqs[e1].coef[q]) != 0)
                  goto foundPQ;
                  goto foundPQ;
 
 
            continue;
            continue;
 
 
          foundPQ:
          foundPQ:
            pz = ((zeqs[e1] & zeqs[e2]) | (peqs[e1] & neqs[e2])
            pz = ((zeqs[e1] & zeqs[e2]) | (peqs[e1] & neqs[e2])
                  | (neqs[e1] & peqs[e2]));
                  | (neqs[e1] & peqs[e2]));
            pp = peqs[e1] | peqs[e2];
            pp = peqs[e1] | peqs[e2];
            pn = neqs[e1] | neqs[e2];
            pn = neqs[e1] | neqs[e2];
 
 
            for (e3 = pb->num_geqs - 1; e3 >= 0; e3--)
            for (e3 = pb->num_geqs - 1; e3 >= 0; e3--)
              if (e3 != e1 && e3 != e2)
              if (e3 != e1 && e3 != e2)
                {
                {
                  if (!implies (zeqs[e3], pz))
                  if (!implies (zeqs[e3], pz))
                    goto nextE3;
                    goto nextE3;
 
 
                  alpha1 = (pb->geqs[e2].coef[q] * pb->geqs[e3].coef[p]
                  alpha1 = (pb->geqs[e2].coef[q] * pb->geqs[e3].coef[p]
                            - pb->geqs[e2].coef[p] * pb->geqs[e3].coef[q]);
                            - pb->geqs[e2].coef[p] * pb->geqs[e3].coef[q]);
                  alpha2 = -(pb->geqs[e1].coef[q] * pb->geqs[e3].coef[p]
                  alpha2 = -(pb->geqs[e1].coef[q] * pb->geqs[e3].coef[p]
                             - pb->geqs[e1].coef[p] * pb->geqs[e3].coef[q]);
                             - pb->geqs[e1].coef[p] * pb->geqs[e3].coef[q]);
                  alpha3 = alpha;
                  alpha3 = alpha;
 
 
                  if (alpha1 * alpha2 <= 0)
                  if (alpha1 * alpha2 <= 0)
                    goto nextE3;
                    goto nextE3;
 
 
                  if (alpha1 < 0)
                  if (alpha1 < 0)
                    {
                    {
                      alpha1 = -alpha1;
                      alpha1 = -alpha1;
                      alpha2 = -alpha2;
                      alpha2 = -alpha2;
                      alpha3 = -alpha3;
                      alpha3 = -alpha3;
                    }
                    }
 
 
                  if (alpha3 > 0)
                  if (alpha3 > 0)
                    {
                    {
                      /* Trying to prove e3 is redundant.  */
                      /* Trying to prove e3 is redundant.  */
                      if (!implies (peqs[e3], pp)
                      if (!implies (peqs[e3], pp)
                          || !implies (neqs[e3], pn))
                          || !implies (neqs[e3], pn))
                        goto nextE3;
                        goto nextE3;
 
 
                      if (pb->geqs[e3].color == omega_black
                      if (pb->geqs[e3].color == omega_black
                          && (pb->geqs[e1].color == omega_red
                          && (pb->geqs[e1].color == omega_red
                              || pb->geqs[e2].color == omega_red))
                              || pb->geqs[e2].color == omega_red))
                        goto nextE3;
                        goto nextE3;
 
 
                      for (k = pb->num_vars; k >= 1; k--)
                      for (k = pb->num_vars; k >= 1; k--)
                        if (alpha3 * pb->geqs[e3].coef[k]
                        if (alpha3 * pb->geqs[e3].coef[k]
                            != (alpha1 * pb->geqs[e1].coef[k]
                            != (alpha1 * pb->geqs[e1].coef[k]
                                + alpha2 * pb->geqs[e2].coef[k]))
                                + alpha2 * pb->geqs[e2].coef[k]))
                          goto nextE3;
                          goto nextE3;
 
 
                      c = (alpha1 * pb->geqs[e1].coef[0]
                      c = (alpha1 * pb->geqs[e1].coef[0]
                           + alpha2 * pb->geqs[e2].coef[0]);
                           + alpha2 * pb->geqs[e2].coef[0]);
 
 
                      if (c < alpha3 * (pb->geqs[e3].coef[0] + 1))
                      if (c < alpha3 * (pb->geqs[e3].coef[0] + 1))
                        {
                        {
                          if (dump_file && (dump_flags & TDF_DETAILS))
                          if (dump_file && (dump_flags & TDF_DETAILS))
                            {
                            {
                              fprintf (dump_file,
                              fprintf (dump_file,
                                       "found redundant inequality\n");
                                       "found redundant inequality\n");
                              fprintf (dump_file,
                              fprintf (dump_file,
                                       "alpha1, alpha2, alpha3 = %d,%d,%d\n",
                                       "alpha1, alpha2, alpha3 = %d,%d,%d\n",
                                       alpha1, alpha2, alpha3);
                                       alpha1, alpha2, alpha3);
 
 
                              omega_print_geq (dump_file, pb, &(pb->geqs[e1]));
                              omega_print_geq (dump_file, pb, &(pb->geqs[e1]));
                              fprintf (dump_file, "\n");
                              fprintf (dump_file, "\n");
                              omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
                              omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
                              fprintf (dump_file, "\n=> ");
                              fprintf (dump_file, "\n=> ");
                              omega_print_geq (dump_file, pb, &(pb->geqs[e3]));
                              omega_print_geq (dump_file, pb, &(pb->geqs[e3]));
                              fprintf (dump_file, "\n\n");
                              fprintf (dump_file, "\n\n");
                            }
                            }
 
 
                          is_dead[e3] = true;
                          is_dead[e3] = true;
                        }
                        }
                    }
                    }
                  else
                  else
                    {
                    {
                      /* Trying to prove e3 <= 0 and therefore e3 = 0,
                      /* Trying to prove e3 <= 0 and therefore e3 = 0,
                        or trying to prove e3 < 0, and therefore the
                        or trying to prove e3 < 0, and therefore the
                        problem has no solutions.  */
                        problem has no solutions.  */
                      if (!implies (peqs[e3], pn)
                      if (!implies (peqs[e3], pn)
                          || !implies (neqs[e3], pp))
                          || !implies (neqs[e3], pp))
                        goto nextE3;
                        goto nextE3;
 
 
                      if (pb->geqs[e1].color == omega_red
                      if (pb->geqs[e1].color == omega_red
                          || pb->geqs[e2].color == omega_red
                          || pb->geqs[e2].color == omega_red
                          || pb->geqs[e3].color == omega_red)
                          || pb->geqs[e3].color == omega_red)
                        goto nextE3;
                        goto nextE3;
 
 
                      alpha3 = alpha3;
                      alpha3 = alpha3;
                      /* verify alpha1*v1+alpha2*v2 = alpha3*v3 */
                      /* verify alpha1*v1+alpha2*v2 = alpha3*v3 */
                      for (k = pb->num_vars; k >= 1; k--)
                      for (k = pb->num_vars; k >= 1; k--)
                        if (alpha3 * pb->geqs[e3].coef[k]
                        if (alpha3 * pb->geqs[e3].coef[k]
                            != (alpha1 * pb->geqs[e1].coef[k]
                            != (alpha1 * pb->geqs[e1].coef[k]
                                + alpha2 * pb->geqs[e2].coef[k]))
                                + alpha2 * pb->geqs[e2].coef[k]))
                          goto nextE3;
                          goto nextE3;
 
 
                      c = (alpha1 * pb->geqs[e1].coef[0]
                      c = (alpha1 * pb->geqs[e1].coef[0]
                           + alpha2 * pb->geqs[e2].coef[0]);
                           + alpha2 * pb->geqs[e2].coef[0]);
 
 
                      if (c < alpha3 * (pb->geqs[e3].coef[0]))
                      if (c < alpha3 * (pb->geqs[e3].coef[0]))
                        {
                        {
                          /* We just proved e3 < 0, so no solutions exist.  */
                          /* We just proved e3 < 0, so no solutions exist.  */
                          if (dump_file && (dump_flags & TDF_DETAILS))
                          if (dump_file && (dump_flags & TDF_DETAILS))
                            {
                            {
                              fprintf (dump_file,
                              fprintf (dump_file,
                                       "found implied over tight inequality\n");
                                       "found implied over tight inequality\n");
                              fprintf (dump_file,
                              fprintf (dump_file,
                                       "alpha1, alpha2, alpha3 = %d,%d,%d\n",
                                       "alpha1, alpha2, alpha3 = %d,%d,%d\n",
                                       alpha1, alpha2, -alpha3);
                                       alpha1, alpha2, -alpha3);
                              omega_print_geq (dump_file, pb, &(pb->geqs[e1]));
                              omega_print_geq (dump_file, pb, &(pb->geqs[e1]));
                              fprintf (dump_file, "\n");
                              fprintf (dump_file, "\n");
                              omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
                              omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
                              fprintf (dump_file, "\n=> not ");
                              fprintf (dump_file, "\n=> not ");
                              omega_print_geq (dump_file, pb, &(pb->geqs[e3]));
                              omega_print_geq (dump_file, pb, &(pb->geqs[e3]));
                              fprintf (dump_file, "\n\n");
                              fprintf (dump_file, "\n\n");
                            }
                            }
                          free (is_dead);
                          free (is_dead);
                          free (peqs);
                          free (peqs);
                          free (zeqs);
                          free (zeqs);
                          free (neqs);
                          free (neqs);
                          return omega_false;
                          return omega_false;
                        }
                        }
                      else if (c < alpha3 * (pb->geqs[e3].coef[0] - 1))
                      else if (c < alpha3 * (pb->geqs[e3].coef[0] - 1))
                        {
                        {
                          /* We just proved that e3 <=0, so e3 = 0.  */
                          /* We just proved that e3 <=0, so e3 = 0.  */
                          if (dump_file && (dump_flags & TDF_DETAILS))
                          if (dump_file && (dump_flags & TDF_DETAILS))
                            {
                            {
                              fprintf (dump_file,
                              fprintf (dump_file,
                                       "found implied tight inequality\n");
                                       "found implied tight inequality\n");
                              fprintf (dump_file,
                              fprintf (dump_file,
                                       "alpha1, alpha2, alpha3 = %d,%d,%d\n",
                                       "alpha1, alpha2, alpha3 = %d,%d,%d\n",
                                       alpha1, alpha2, -alpha3);
                                       alpha1, alpha2, -alpha3);
                              omega_print_geq (dump_file, pb, &(pb->geqs[e1]));
                              omega_print_geq (dump_file, pb, &(pb->geqs[e1]));
                              fprintf (dump_file, "\n");
                              fprintf (dump_file, "\n");
                              omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
                              omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
                              fprintf (dump_file, "\n=> inverse ");
                              fprintf (dump_file, "\n=> inverse ");
                              omega_print_geq (dump_file, pb, &(pb->geqs[e3]));
                              omega_print_geq (dump_file, pb, &(pb->geqs[e3]));
                              fprintf (dump_file, "\n\n");
                              fprintf (dump_file, "\n\n");
                            }
                            }
 
 
                          omega_copy_eqn (&pb->eqs[pb->num_eqs++],
                          omega_copy_eqn (&pb->eqs[pb->num_eqs++],
                                          &pb->geqs[e3], pb->num_vars);
                                          &pb->geqs[e3], pb->num_vars);
                          gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
                          gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
                          adding_equality_constraint (pb, pb->num_eqs - 1);
                          adding_equality_constraint (pb, pb->num_eqs - 1);
                          is_dead[e3] = true;
                          is_dead[e3] = true;
                        }
                        }
                    }
                    }
                nextE3:;
                nextE3:;
                }
                }
          }
          }
 
 
  /* Delete the inequalities that were marked as dead.  */
  /* Delete the inequalities that were marked as dead.  */
  for (e = pb->num_geqs - 1; e >= 0; e--)
  for (e = pb->num_geqs - 1; e >= 0; e--)
    if (is_dead[e])
    if (is_dead[e])
      omega_delete_geq (pb, e, pb->num_vars);
      omega_delete_geq (pb, e, pb->num_vars);
 
 
  if (!expensive)
  if (!expensive)
    goto eliminate_redundant_done;
    goto eliminate_redundant_done;
 
 
  tmp_problem = XNEW (struct omega_pb_d);
  tmp_problem = XNEW (struct omega_pb_d);
  conservative++;
  conservative++;
 
 
  for (e = pb->num_geqs - 1; e >= 0; e--)
  for (e = pb->num_geqs - 1; e >= 0; e--)
    {
    {
      if (dump_file && (dump_flags & TDF_DETAILS))
      if (dump_file && (dump_flags & TDF_DETAILS))
        {
        {
          fprintf (dump_file,
          fprintf (dump_file,
                   "checking equation %d to see if it is redundant: ", e);
                   "checking equation %d to see if it is redundant: ", e);
          omega_print_geq (dump_file, pb, &(pb->geqs[e]));
          omega_print_geq (dump_file, pb, &(pb->geqs[e]));
          fprintf (dump_file, "\n");
          fprintf (dump_file, "\n");
        }
        }
 
 
      omega_copy_problem (tmp_problem, pb);
      omega_copy_problem (tmp_problem, pb);
      omega_negate_geq (tmp_problem, e);
      omega_negate_geq (tmp_problem, e);
      tmp_problem->safe_vars = 0;
      tmp_problem->safe_vars = 0;
      tmp_problem->variables_freed = false;
      tmp_problem->variables_freed = false;
 
 
      if (omega_solve_problem (tmp_problem, omega_false) == omega_false)
      if (omega_solve_problem (tmp_problem, omega_false) == omega_false)
        omega_delete_geq (pb, e, pb->num_vars);
        omega_delete_geq (pb, e, pb->num_vars);
    }
    }
 
 
  free (tmp_problem);
  free (tmp_problem);
  conservative--;
  conservative--;
 
 
  if (!omega_reduce_with_subs)
  if (!omega_reduce_with_subs)
    {
    {
      resurrect_subs (pb);
      resurrect_subs (pb);
      gcc_assert (please_no_equalities_in_simplified_problems
      gcc_assert (please_no_equalities_in_simplified_problems
                  || pb->num_subs == 0);
                  || pb->num_subs == 0);
    }
    }
 
 
 eliminate_redundant_done:
 eliminate_redundant_done:
  free (is_dead);
  free (is_dead);
  free (peqs);
  free (peqs);
  free (zeqs);
  free (zeqs);
  free (neqs);
  free (neqs);
  return omega_true;
  return omega_true;
}
}
 
 
/* For each inequality that has coefficients bigger than 20, try to
/* For each inequality that has coefficients bigger than 20, try to
   create a new constraint that cannot be derived from the original
   create a new constraint that cannot be derived from the original
   constraint and that has smaller coefficients.  Add the new
   constraint and that has smaller coefficients.  Add the new
   constraint at the end of geqs.  Return the number of inequalities
   constraint at the end of geqs.  Return the number of inequalities
   that have been added to PB.  */
   that have been added to PB.  */
 
 
static int
static int
smooth_weird_equations (omega_pb pb)
smooth_weird_equations (omega_pb pb)
{
{
  int e1, e2, e3, p, q, k, alpha, alpha1, alpha2, alpha3;
  int e1, e2, e3, p, q, k, alpha, alpha1, alpha2, alpha3;
  int c;
  int c;
  int v;
  int v;
  int result = 0;
  int result = 0;
 
 
  for (e1 = pb->num_geqs - 1; e1 >= 0; e1--)
  for (e1 = pb->num_geqs - 1; e1 >= 0; e1--)
    if (pb->geqs[e1].color == omega_black)
    if (pb->geqs[e1].color == omega_black)
      {
      {
        int g = 999999;
        int g = 999999;
 
 
        for (v = pb->num_vars; v >= 1; v--)
        for (v = pb->num_vars; v >= 1; v--)
          if (pb->geqs[e1].coef[v] != 0 && abs (pb->geqs[e1].coef[v]) < g)
          if (pb->geqs[e1].coef[v] != 0 && abs (pb->geqs[e1].coef[v]) < g)
            g = abs (pb->geqs[e1].coef[v]);
            g = abs (pb->geqs[e1].coef[v]);
 
 
        /* Magic number.  */
        /* Magic number.  */
        if (g > 20)
        if (g > 20)
          {
          {
            e3 = pb->num_geqs;
            e3 = pb->num_geqs;
 
 
            for (v = pb->num_vars; v >= 1; v--)
            for (v = pb->num_vars; v >= 1; v--)
              pb->geqs[e3].coef[v] = int_div (6 * pb->geqs[e1].coef[v] + g / 2,
              pb->geqs[e3].coef[v] = int_div (6 * pb->geqs[e1].coef[v] + g / 2,
                                              g);
                                              g);
 
 
            pb->geqs[e3].color = omega_black;
            pb->geqs[e3].color = omega_black;
            pb->geqs[e3].touched = 1;
            pb->geqs[e3].touched = 1;
            /* Magic number.  */
            /* Magic number.  */
            pb->geqs[e3].coef[0] = 9997;
            pb->geqs[e3].coef[0] = 9997;
 
 
            if (dump_file && (dump_flags & TDF_DETAILS))
            if (dump_file && (dump_flags & TDF_DETAILS))
              {
              {
                fprintf (dump_file, "Checking to see if we can derive: ");
                fprintf (dump_file, "Checking to see if we can derive: ");
                omega_print_geq (dump_file, pb, &pb->geqs[e3]);
                omega_print_geq (dump_file, pb, &pb->geqs[e3]);
                fprintf (dump_file, "\n from: ");
                fprintf (dump_file, "\n from: ");
                omega_print_geq (dump_file, pb, &pb->geqs[e1]);
                omega_print_geq (dump_file, pb, &pb->geqs[e1]);
                fprintf (dump_file, "\n");
                fprintf (dump_file, "\n");
              }
              }
 
 
            for (e2 = pb->num_geqs - 1; e2 >= 0; e2--)
            for (e2 = pb->num_geqs - 1; e2 >= 0; e2--)
              if (e1 != e2 && pb->geqs[e2].color == omega_black)
              if (e1 != e2 && pb->geqs[e2].color == omega_black)
                {
                {
                  for (p = pb->num_vars; p > 1; p--)
                  for (p = pb->num_vars; p > 1; p--)
                    {
                    {
                      for (q = p - 1; q > 0; q--)
                      for (q = p - 1; q > 0; q--)
                        {
                        {
                          alpha =
                          alpha =
                            (pb->geqs[e1].coef[p] * pb->geqs[e2].coef[q] -
                            (pb->geqs[e1].coef[p] * pb->geqs[e2].coef[q] -
                             pb->geqs[e2].coef[p] * pb->geqs[e1].coef[q]);
                             pb->geqs[e2].coef[p] * pb->geqs[e1].coef[q]);
                          if (alpha != 0)
                          if (alpha != 0)
                            goto foundPQ;
                            goto foundPQ;
                        }
                        }
                    }
                    }
                  continue;
                  continue;
 
 
                foundPQ:
                foundPQ:
 
 
                  alpha1 = (pb->geqs[e2].coef[q] * pb->geqs[e3].coef[p]
                  alpha1 = (pb->geqs[e2].coef[q] * pb->geqs[e3].coef[p]
                            - pb->geqs[e2].coef[p] * pb->geqs[e3].coef[q]);
                            - pb->geqs[e2].coef[p] * pb->geqs[e3].coef[q]);
                  alpha2 = -(pb->geqs[e1].coef[q] * pb->geqs[e3].coef[p]
                  alpha2 = -(pb->geqs[e1].coef[q] * pb->geqs[e3].coef[p]
                             - pb->geqs[e1].coef[p] * pb->geqs[e3].coef[q]);
                             - pb->geqs[e1].coef[p] * pb->geqs[e3].coef[q]);
                  alpha3 = alpha;
                  alpha3 = alpha;
 
 
                  if (alpha1 * alpha2 <= 0)
                  if (alpha1 * alpha2 <= 0)
                    continue;
                    continue;
 
 
                  if (alpha1 < 0)
                  if (alpha1 < 0)
                    {
                    {
                      alpha1 = -alpha1;
                      alpha1 = -alpha1;
                      alpha2 = -alpha2;
                      alpha2 = -alpha2;
                      alpha3 = -alpha3;
                      alpha3 = -alpha3;
                    }
                    }
 
 
                  if (alpha3 > 0)
                  if (alpha3 > 0)
                    {
                    {
                      /* Try to prove e3 is redundant: verify
                      /* Try to prove e3 is redundant: verify
                         alpha1*v1 + alpha2*v2 = alpha3*v3.  */
                         alpha1*v1 + alpha2*v2 = alpha3*v3.  */
                      for (k = pb->num_vars; k >= 1; k--)
                      for (k = pb->num_vars; k >= 1; k--)
                        if (alpha3 * pb->geqs[e3].coef[k]
                        if (alpha3 * pb->geqs[e3].coef[k]
                            != (alpha1 * pb->geqs[e1].coef[k]
                            != (alpha1 * pb->geqs[e1].coef[k]
                                + alpha2 * pb->geqs[e2].coef[k]))
                                + alpha2 * pb->geqs[e2].coef[k]))
                          goto nextE2;
                          goto nextE2;
 
 
                      c = alpha1 * pb->geqs[e1].coef[0]
                      c = alpha1 * pb->geqs[e1].coef[0]
                        + alpha2 * pb->geqs[e2].coef[0];
                        + alpha2 * pb->geqs[e2].coef[0];
 
 
                      if (c < alpha3 * (pb->geqs[e3].coef[0] + 1))
                      if (c < alpha3 * (pb->geqs[e3].coef[0] + 1))
                        pb->geqs[e3].coef[0] = int_div (c, alpha3);
                        pb->geqs[e3].coef[0] = int_div (c, alpha3);
                    }
                    }
                nextE2:;
                nextE2:;
                }
                }
 
 
            if (pb->geqs[e3].coef[0] < 9997)
            if (pb->geqs[e3].coef[0] < 9997)
              {
              {
                result++;
                result++;
                pb->num_geqs++;
                pb->num_geqs++;
 
 
                if (dump_file && (dump_flags & TDF_DETAILS))
                if (dump_file && (dump_flags & TDF_DETAILS))
                  {
                  {
                    fprintf (dump_file,
                    fprintf (dump_file,
                             "Smoothing weird equations; adding:\n");
                             "Smoothing weird equations; adding:\n");
                    omega_print_geq (dump_file, pb, &pb->geqs[e3]);
                    omega_print_geq (dump_file, pb, &pb->geqs[e3]);
                    fprintf (dump_file, "\nto:\n");
                    fprintf (dump_file, "\nto:\n");
                    omega_print_problem (dump_file, pb);
                    omega_print_problem (dump_file, pb);
                    fprintf (dump_file, "\n\n");
                    fprintf (dump_file, "\n\n");
                  }
                  }
              }
              }
          }
          }
      }
      }
  return result;
  return result;
}
}
 
 
/* Replace tuples of inequalities, that define upper and lower half
/* Replace tuples of inequalities, that define upper and lower half
   spaces, with an equation.  */
   spaces, with an equation.  */
 
 
static void
static void
coalesce (omega_pb pb)
coalesce (omega_pb pb)
{
{
  int e, e2;
  int e, e2;
  int colors = 0;
  int colors = 0;
  bool *is_dead;
  bool *is_dead;
  int found_something = 0;
  int found_something = 0;
 
 
  for (e = 0; e < pb->num_geqs; e++)
  for (e = 0; e < pb->num_geqs; e++)
    if (pb->geqs[e].color == omega_red)
    if (pb->geqs[e].color == omega_red)
      colors++;
      colors++;
 
 
  if (colors < 2)
  if (colors < 2)
    return;
    return;
 
 
  is_dead = XNEWVEC (bool, OMEGA_MAX_GEQS);
  is_dead = XNEWVEC (bool, OMEGA_MAX_GEQS);
 
 
  for (e = 0; e < pb->num_geqs; e++)
  for (e = 0; e < pb->num_geqs; e++)
    is_dead[e] = false;
    is_dead[e] = false;
 
 
  for (e = 0; e < pb->num_geqs; e++)
  for (e = 0; e < pb->num_geqs; e++)
    if (pb->geqs[e].color == omega_red
    if (pb->geqs[e].color == omega_red
        && !pb->geqs[e].touched)
        && !pb->geqs[e].touched)
      for (e2 = e + 1; e2 < pb->num_geqs; e2++)
      for (e2 = e + 1; e2 < pb->num_geqs; e2++)
        if (!pb->geqs[e2].touched
        if (!pb->geqs[e2].touched
            && pb->geqs[e].key == -pb->geqs[e2].key
            && pb->geqs[e].key == -pb->geqs[e2].key
            && pb->geqs[e].coef[0] == -pb->geqs[e2].coef[0]
            && pb->geqs[e].coef[0] == -pb->geqs[e2].coef[0]
            && pb->geqs[e2].color == omega_red)
            && pb->geqs[e2].color == omega_red)
          {
          {
            omega_copy_eqn (&pb->eqs[pb->num_eqs++], &pb->geqs[e],
            omega_copy_eqn (&pb->eqs[pb->num_eqs++], &pb->geqs[e],
                            pb->num_vars);
                            pb->num_vars);
            gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
            gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
            found_something++;
            found_something++;
            is_dead[e] = true;
            is_dead[e] = true;
            is_dead[e2] = true;
            is_dead[e2] = true;
          }
          }
 
 
  for (e = pb->num_geqs - 1; e >= 0; e--)
  for (e = pb->num_geqs - 1; e >= 0; e--)
    if (is_dead[e])
    if (is_dead[e])
      omega_delete_geq (pb, e, pb->num_vars);
      omega_delete_geq (pb, e, pb->num_vars);
 
 
  if (dump_file && (dump_flags & TDF_DETAILS) && found_something)
  if (dump_file && (dump_flags & TDF_DETAILS) && found_something)
    {
    {
      fprintf (dump_file, "Coalesced pb->geqs into %d EQ's:\n",
      fprintf (dump_file, "Coalesced pb->geqs into %d EQ's:\n",
               found_something);
               found_something);
      omega_print_problem (dump_file, pb);
      omega_print_problem (dump_file, pb);
    }
    }
 
 
  free (is_dead);
  free (is_dead);
}
}
 
 
/* Eliminate red inequalities from PB.  When ELIMINATE_ALL is
/* Eliminate red inequalities from PB.  When ELIMINATE_ALL is
   true, continue to eliminate all the red inequalities.  */
   true, continue to eliminate all the red inequalities.  */
 
 
void
void
omega_eliminate_red (omega_pb pb, bool eliminate_all)
omega_eliminate_red (omega_pb pb, bool eliminate_all)
{
{
  int e, e2, e3, i, j, k, a, alpha1, alpha2;
  int e, e2, e3, i, j, k, a, alpha1, alpha2;
  int c = 0;
  int c = 0;
  bool *is_dead = XNEWVEC (bool, OMEGA_MAX_GEQS);
  bool *is_dead = XNEWVEC (bool, OMEGA_MAX_GEQS);
  int dead_count = 0;
  int dead_count = 0;
  int red_found;
  int red_found;
  omega_pb tmp_problem;
  omega_pb tmp_problem;
 
 
  if (dump_file && (dump_flags & TDF_DETAILS))
  if (dump_file && (dump_flags & TDF_DETAILS))
    {
    {
      fprintf (dump_file, "in eliminate RED:\n");
      fprintf (dump_file, "in eliminate RED:\n");
      omega_print_problem (dump_file, pb);
      omega_print_problem (dump_file, pb);
    }
    }
 
 
  if (pb->num_eqs > 0)
  if (pb->num_eqs > 0)
    omega_simplify_problem (pb);
    omega_simplify_problem (pb);
 
 
  for (e = pb->num_geqs - 1; e >= 0; e--)
  for (e = pb->num_geqs - 1; e >= 0; e--)
    is_dead[e] = false;
    is_dead[e] = false;
 
 
  for (e = pb->num_geqs - 1; e >= 0; e--)
  for (e = pb->num_geqs - 1; e >= 0; e--)
    if (pb->geqs[e].color == omega_black && !is_dead[e])
    if (pb->geqs[e].color == omega_black && !is_dead[e])
      for (e2 = e - 1; e2 >= 0; e2--)
      for (e2 = e - 1; e2 >= 0; e2--)
        if (pb->geqs[e2].color == omega_black
        if (pb->geqs[e2].color == omega_black
            && !is_dead[e2])
            && !is_dead[e2])
          {
          {
            a = 0;
            a = 0;
 
 
            for (i = pb->num_vars; i > 1; i--)
            for (i = pb->num_vars; i > 1; i--)
              for (j = i - 1; j > 0; j--)
              for (j = i - 1; j > 0; j--)
                if ((a = (pb->geqs[e].coef[i] * pb->geqs[e2].coef[j]
                if ((a = (pb->geqs[e].coef[i] * pb->geqs[e2].coef[j]
                          - pb->geqs[e2].coef[i] * pb->geqs[e].coef[j])) != 0)
                          - pb->geqs[e2].coef[i] * pb->geqs[e].coef[j])) != 0)
                  goto found_pair;
                  goto found_pair;
 
 
            continue;
            continue;
 
 
          found_pair:
          found_pair:
            if (dump_file && (dump_flags & TDF_DETAILS))
            if (dump_file && (dump_flags & TDF_DETAILS))
              {
              {
                fprintf (dump_file,
                fprintf (dump_file,
                         "found two equations to combine, i = %s, ",
                         "found two equations to combine, i = %s, ",
                         omega_variable_to_str (pb, i));
                         omega_variable_to_str (pb, i));
                fprintf (dump_file, "j = %s, alpha = %d\n",
                fprintf (dump_file, "j = %s, alpha = %d\n",
                         omega_variable_to_str (pb, j), a);
                         omega_variable_to_str (pb, j), a);
                omega_print_geq (dump_file, pb, &(pb->geqs[e]));
                omega_print_geq (dump_file, pb, &(pb->geqs[e]));
                fprintf (dump_file, "\n");
                fprintf (dump_file, "\n");
                omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
                omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
                fprintf (dump_file, "\n");
                fprintf (dump_file, "\n");
              }
              }
 
 
            for (e3 = pb->num_geqs - 1; e3 >= 0; e3--)
            for (e3 = pb->num_geqs - 1; e3 >= 0; e3--)
              if (pb->geqs[e3].color == omega_red)
              if (pb->geqs[e3].color == omega_red)
                {
                {
                  alpha1 = (pb->geqs[e2].coef[j] * pb->geqs[e3].coef[i]
                  alpha1 = (pb->geqs[e2].coef[j] * pb->geqs[e3].coef[i]
                            - pb->geqs[e2].coef[i] * pb->geqs[e3].coef[j]);
                            - pb->geqs[e2].coef[i] * pb->geqs[e3].coef[j]);
                  alpha2 = -(pb->geqs[e].coef[j] * pb->geqs[e3].coef[i]
                  alpha2 = -(pb->geqs[e].coef[j] * pb->geqs[e3].coef[i]
                             - pb->geqs[e].coef[i] * pb->geqs[e3].coef[j]);
                             - pb->geqs[e].coef[i] * pb->geqs[e3].coef[j]);
 
 
                  if ((a > 0 && alpha1 > 0 && alpha2 > 0)
                  if ((a > 0 && alpha1 > 0 && alpha2 > 0)
                      || (a < 0 && alpha1 < 0 && alpha2 < 0))
                      || (a < 0 && alpha1 < 0 && alpha2 < 0))
                    {
                    {
                      if (dump_file && (dump_flags & TDF_DETAILS))
                      if (dump_file && (dump_flags & TDF_DETAILS))
                        {
                        {
                          fprintf (dump_file,
                          fprintf (dump_file,
                                   "alpha1 = %d, alpha2 = %d;"
                                   "alpha1 = %d, alpha2 = %d;"
                                   "comparing against: ",
                                   "comparing against: ",
                                   alpha1, alpha2);
                                   alpha1, alpha2);
                          omega_print_geq (dump_file, pb, &(pb->geqs[e3]));
                          omega_print_geq (dump_file, pb, &(pb->geqs[e3]));
                          fprintf (dump_file, "\n");
                          fprintf (dump_file, "\n");
                        }
                        }
 
 
                      for (k = pb->num_vars; k >= 0; k--)
                      for (k = pb->num_vars; k >= 0; k--)
                        {
                        {
                          c = (alpha1 * pb->geqs[e].coef[k]
                          c = (alpha1 * pb->geqs[e].coef[k]
                               + alpha2 * pb->geqs[e2].coef[k]);
                               + alpha2 * pb->geqs[e2].coef[k]);
 
 
                          if (c != a * pb->geqs[e3].coef[k])
                          if (c != a * pb->geqs[e3].coef[k])
                            break;
                            break;
 
 
                          if (dump_file && (dump_flags & TDF_DETAILS) && k > 0)
                          if (dump_file && (dump_flags & TDF_DETAILS) && k > 0)
                            fprintf (dump_file, " %s: %d, %d\n",
                            fprintf (dump_file, " %s: %d, %d\n",
                                     omega_variable_to_str (pb, k), c,
                                     omega_variable_to_str (pb, k), c,
                                     a * pb->geqs[e3].coef[k]);
                                     a * pb->geqs[e3].coef[k]);
                        }
                        }
 
 
                      if (k < 0
                      if (k < 0
                          || (k == 0 &&
                          || (k == 0 &&
                              ((a > 0 && c < a * pb->geqs[e3].coef[k])
                              ((a > 0 && c < a * pb->geqs[e3].coef[k])
                               || (a < 0 && c > a * pb->geqs[e3].coef[k]))))
                               || (a < 0 && c > a * pb->geqs[e3].coef[k]))))
                        {
                        {
                          if (dump_file && (dump_flags & TDF_DETAILS))
                          if (dump_file && (dump_flags & TDF_DETAILS))
                            {
                            {
                              dead_count++;
                              dead_count++;
                              fprintf (dump_file,
                              fprintf (dump_file,
                                       "red equation#%d is dead "
                                       "red equation#%d is dead "
                                       "(%d dead so far, %d remain)\n",
                                       "(%d dead so far, %d remain)\n",
                                       e3, dead_count,
                                       e3, dead_count,
                                       pb->num_geqs - dead_count);
                                       pb->num_geqs - dead_count);
                              omega_print_geq (dump_file, pb, &(pb->geqs[e]));
                              omega_print_geq (dump_file, pb, &(pb->geqs[e]));
                              fprintf (dump_file, "\n");
                              fprintf (dump_file, "\n");
                              omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
                              omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
                              fprintf (dump_file, "\n");
                              fprintf (dump_file, "\n");
                              omega_print_geq (dump_file, pb, &(pb->geqs[e3]));
                              omega_print_geq (dump_file, pb, &(pb->geqs[e3]));
                              fprintf (dump_file, "\n");
                              fprintf (dump_file, "\n");
                            }
                            }
                          is_dead[e3] = true;
                          is_dead[e3] = true;
                        }
                        }
                    }
                    }
                }
                }
          }
          }
 
 
  for (e = pb->num_geqs - 1; e >= 0; e--)
  for (e = pb->num_geqs - 1; e >= 0; e--)
    if (is_dead[e])
    if (is_dead[e])
      omega_delete_geq (pb, e, pb->num_vars);
      omega_delete_geq (pb, e, pb->num_vars);
 
 
  free (is_dead);
  free (is_dead);
 
 
  if (dump_file && (dump_flags & TDF_DETAILS))
  if (dump_file && (dump_flags & TDF_DETAILS))
    {
    {
      fprintf (dump_file, "in eliminate RED, easy tests done:\n");
      fprintf (dump_file, "in eliminate RED, easy tests done:\n");
      omega_print_problem (dump_file, pb);
      omega_print_problem (dump_file, pb);
    }
    }
 
 
  for (red_found = 0, e = pb->num_geqs - 1; e >= 0; e--)
  for (red_found = 0, e = pb->num_geqs - 1; e >= 0; e--)
    if (pb->geqs[e].color == omega_red)
    if (pb->geqs[e].color == omega_red)
      red_found = 1;
      red_found = 1;
 
 
  if (!red_found)
  if (!red_found)
    {
    {
      if (dump_file && (dump_flags & TDF_DETAILS))
      if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file, "fast checks worked\n");
        fprintf (dump_file, "fast checks worked\n");
 
 
      if (!omega_reduce_with_subs)
      if (!omega_reduce_with_subs)
        gcc_assert (please_no_equalities_in_simplified_problems
        gcc_assert (please_no_equalities_in_simplified_problems
                    || pb->num_subs == 0);
                    || pb->num_subs == 0);
 
 
      return;
      return;
    }
    }
 
 
  if (!omega_verify_simplification
  if (!omega_verify_simplification
      && verify_omega_pb (pb) == omega_false)
      && verify_omega_pb (pb) == omega_false)
    return;
    return;
 
 
  conservative++;
  conservative++;
  tmp_problem = XNEW (struct omega_pb_d);
  tmp_problem = XNEW (struct omega_pb_d);
 
 
  for (e = pb->num_geqs - 1; e >= 0; e--)
  for (e = pb->num_geqs - 1; e >= 0; e--)
    if (pb->geqs[e].color == omega_red)
    if (pb->geqs[e].color == omega_red)
      {
      {
        if (dump_file && (dump_flags & TDF_DETAILS))
        if (dump_file && (dump_flags & TDF_DETAILS))
          {
          {
            fprintf (dump_file,
            fprintf (dump_file,
                     "checking equation %d to see if it is redundant: ", e);
                     "checking equation %d to see if it is redundant: ", e);
            omega_print_geq (dump_file, pb, &(pb->geqs[e]));
            omega_print_geq (dump_file, pb, &(pb->geqs[e]));
            fprintf (dump_file, "\n");
            fprintf (dump_file, "\n");
          }
          }
 
 
        omega_copy_problem (tmp_problem, pb);
        omega_copy_problem (tmp_problem, pb);
        omega_negate_geq (tmp_problem, e);
        omega_negate_geq (tmp_problem, e);
        tmp_problem->safe_vars = 0;
        tmp_problem->safe_vars = 0;
        tmp_problem->variables_freed = false;
        tmp_problem->variables_freed = false;
        tmp_problem->num_subs = 0;
        tmp_problem->num_subs = 0;
 
 
        if (omega_solve_problem (tmp_problem, omega_false) == omega_false)
        if (omega_solve_problem (tmp_problem, omega_false) == omega_false)
          {
          {
            if (dump_file && (dump_flags & TDF_DETAILS))
            if (dump_file && (dump_flags & TDF_DETAILS))
              fprintf (dump_file, "it is redundant\n");
              fprintf (dump_file, "it is redundant\n");
            omega_delete_geq (pb, e, pb->num_vars);
            omega_delete_geq (pb, e, pb->num_vars);
          }
          }
        else
        else
          {
          {
            if (dump_file && (dump_flags & TDF_DETAILS))
            if (dump_file && (dump_flags & TDF_DETAILS))
              fprintf (dump_file, "it is not redundant\n");
              fprintf (dump_file, "it is not redundant\n");
 
 
            if (!eliminate_all)
            if (!eliminate_all)
              {
              {
                if (dump_file && (dump_flags & TDF_DETAILS))
                if (dump_file && (dump_flags & TDF_DETAILS))
                  fprintf (dump_file, "no need to check other red equations\n");
                  fprintf (dump_file, "no need to check other red equations\n");
                break;
                break;
              }
              }
          }
          }
      }
      }
 
 
  conservative--;
  conservative--;
  free (tmp_problem);
  free (tmp_problem);
  /* omega_simplify_problem (pb); */
  /* omega_simplify_problem (pb); */
 
 
  if (!omega_reduce_with_subs)
  if (!omega_reduce_with_subs)
    gcc_assert (please_no_equalities_in_simplified_problems
    gcc_assert (please_no_equalities_in_simplified_problems
                || pb->num_subs == 0);
                || pb->num_subs == 0);
}
}
 
 
/* Transform some wildcard variables to non-safe variables.  */
/* Transform some wildcard variables to non-safe variables.  */
 
 
static void
static void
chain_unprotect (omega_pb pb)
chain_unprotect (omega_pb pb)
{
{
  int i, e;
  int i, e;
  bool *unprotect = XNEWVEC (bool, OMEGA_MAX_VARS);
  bool *unprotect = XNEWVEC (bool, OMEGA_MAX_VARS);
 
 
  for (i = 1; omega_safe_var_p (pb, i); i++)
  for (i = 1; omega_safe_var_p (pb, i); i++)
    {
    {
      unprotect[i] = omega_wildcard_p (pb, i);
      unprotect[i] = omega_wildcard_p (pb, i);
 
 
      for (e = pb->num_subs - 1; e >= 0; e--)
      for (e = pb->num_subs - 1; e >= 0; e--)
        if (pb->subs[e].coef[i])
        if (pb->subs[e].coef[i])
          unprotect[i] = false;
          unprotect[i] = false;
    }
    }
 
 
  if (dump_file && (dump_flags & TDF_DETAILS))
  if (dump_file && (dump_flags & TDF_DETAILS))
    {
    {
      fprintf (dump_file, "Doing chain reaction unprotection\n");
      fprintf (dump_file, "Doing chain reaction unprotection\n");
      omega_print_problem (dump_file, pb);
      omega_print_problem (dump_file, pb);
 
 
      for (i = 1; omega_safe_var_p (pb, i); i++)
      for (i = 1; omega_safe_var_p (pb, i); i++)
        if (unprotect[i])
        if (unprotect[i])
          fprintf (dump_file, "unprotecting %s\n",
          fprintf (dump_file, "unprotecting %s\n",
                   omega_variable_to_str (pb, i));
                   omega_variable_to_str (pb, i));
    }
    }
 
 
  for (i = 1; omega_safe_var_p (pb, i); i++)
  for (i = 1; omega_safe_var_p (pb, i); i++)
    if (unprotect[i])
    if (unprotect[i])
      omega_unprotect_1 (pb, &i, unprotect);
      omega_unprotect_1 (pb, &i, unprotect);
 
 
  if (dump_file && (dump_flags & TDF_DETAILS))
  if (dump_file && (dump_flags & TDF_DETAILS))
    {
    {
      fprintf (dump_file, "After chain reactions\n");
      fprintf (dump_file, "After chain reactions\n");
      omega_print_problem (dump_file, pb);
      omega_print_problem (dump_file, pb);
    }
    }
 
 
  free (unprotect);
  free (unprotect);
}
}
 
 
/* Reduce problem PB.  */
/* Reduce problem PB.  */
 
 
static void
static void
omega_problem_reduced (omega_pb pb)
omega_problem_reduced (omega_pb pb)
{
{
  if (omega_verify_simplification
  if (omega_verify_simplification
      && !in_approximate_mode
      && !in_approximate_mode
      && verify_omega_pb (pb) == omega_false)
      && verify_omega_pb (pb) == omega_false)
    return;
    return;
 
 
  if (PARAM_VALUE (PARAM_OMEGA_ELIMINATE_REDUNDANT_CONSTRAINTS)
  if (PARAM_VALUE (PARAM_OMEGA_ELIMINATE_REDUNDANT_CONSTRAINTS)
      && !omega_eliminate_redundant (pb, true))
      && !omega_eliminate_redundant (pb, true))
    return;
    return;
 
 
  omega_found_reduction = omega_true;
  omega_found_reduction = omega_true;
 
 
  if (!please_no_equalities_in_simplified_problems)
  if (!please_no_equalities_in_simplified_problems)
    coalesce (pb);
    coalesce (pb);
 
 
  if (omega_reduce_with_subs
  if (omega_reduce_with_subs
      || please_no_equalities_in_simplified_problems)
      || please_no_equalities_in_simplified_problems)
    chain_unprotect (pb);
    chain_unprotect (pb);
  else
  else
    resurrect_subs (pb);
    resurrect_subs (pb);
 
 
  if (!return_single_result)
  if (!return_single_result)
    {
    {
      int i;
      int i;
 
 
      for (i = 1; omega_safe_var_p (pb, i); i++)
      for (i = 1; omega_safe_var_p (pb, i); i++)
        pb->forwarding_address[pb->var[i]] = i;
        pb->forwarding_address[pb->var[i]] = i;
 
 
      for (i = 0; i < pb->num_subs; i++)
      for (i = 0; i < pb->num_subs; i++)
        pb->forwarding_address[pb->subs[i].key] = -i - 1;
        pb->forwarding_address[pb->subs[i].key] = -i - 1;
 
 
      (*omega_when_reduced) (pb);
      (*omega_when_reduced) (pb);
    }
    }
 
 
  if (dump_file && (dump_flags & TDF_DETAILS))
  if (dump_file && (dump_flags & TDF_DETAILS))
    {
    {
      fprintf (dump_file, "-------------------------------------------\n");
      fprintf (dump_file, "-------------------------------------------\n");
      fprintf (dump_file, "problem reduced:\n");
      fprintf (dump_file, "problem reduced:\n");
      omega_print_problem (dump_file, pb);
      omega_print_problem (dump_file, pb);
      fprintf (dump_file, "-------------------------------------------\n");
      fprintf (dump_file, "-------------------------------------------\n");
    }
    }
}
}
 
 
/* Eliminates all the free variables for problem PB, that is all the
/* Eliminates all the free variables for problem PB, that is all the
   variables from FV to PB->NUM_VARS.  */
   variables from FV to PB->NUM_VARS.  */
 
 
static void
static void
omega_free_eliminations (omega_pb pb, int fv)
omega_free_eliminations (omega_pb pb, int fv)
{
{
  bool try_again = true;
  bool try_again = true;
  int i, e, e2;
  int i, e, e2;
  int n_vars = pb->num_vars;
  int n_vars = pb->num_vars;
 
 
  while (try_again)
  while (try_again)
    {
    {
      try_again = false;
      try_again = false;
 
 
      for (i = n_vars; i > fv; i--)
      for (i = n_vars; i > fv; i--)
        {
        {
          for (e = pb->num_geqs - 1; e >= 0; e--)
          for (e = pb->num_geqs - 1; e >= 0; e--)
            if (pb->geqs[e].coef[i])
            if (pb->geqs[e].coef[i])
              break;
              break;
 
 
          if (e < 0)
          if (e < 0)
            e2 = e;
            e2 = e;
          else if (pb->geqs[e].coef[i] > 0)
          else if (pb->geqs[e].coef[i] > 0)
            {
            {
              for (e2 = e - 1; e2 >= 0; e2--)
              for (e2 = e - 1; e2 >= 0; e2--)
                if (pb->geqs[e2].coef[i] < 0)
                if (pb->geqs[e2].coef[i] < 0)
                  break;
                  break;
            }
            }
          else
          else
            {
            {
              for (e2 = e - 1; e2 >= 0; e2--)
              for (e2 = e - 1; e2 >= 0; e2--)
                if (pb->geqs[e2].coef[i] > 0)
                if (pb->geqs[e2].coef[i] > 0)
                  break;
                  break;
            }
            }
 
 
          if (e2 < 0)
          if (e2 < 0)
            {
            {
              int e3;
              int e3;
              for (e3 = pb->num_subs - 1; e3 >= 0; e3--)
              for (e3 = pb->num_subs - 1; e3 >= 0; e3--)
                if (pb->subs[e3].coef[i])
                if (pb->subs[e3].coef[i])
                  break;
                  break;
 
 
              if (e3 >= 0)
              if (e3 >= 0)
                continue;
                continue;
 
 
              for (e3 = pb->num_eqs - 1; e3 >= 0; e3--)
              for (e3 = pb->num_eqs - 1; e3 >= 0; e3--)
                if (pb->eqs[e3].coef[i])
                if (pb->eqs[e3].coef[i])
                  break;
                  break;
 
 
              if (e3 >= 0)
              if (e3 >= 0)
                continue;
                continue;
 
 
              if (dump_file && (dump_flags & TDF_DETAILS))
              if (dump_file && (dump_flags & TDF_DETAILS))
                fprintf (dump_file, "a free elimination of %s\n",
                fprintf (dump_file, "a free elimination of %s\n",
                         omega_variable_to_str (pb, i));
                         omega_variable_to_str (pb, i));
 
 
              if (e >= 0)
              if (e >= 0)
                {
                {
                  omega_delete_geq (pb, e, n_vars);
                  omega_delete_geq (pb, e, n_vars);
 
 
                  for (e--; e >= 0; e--)
                  for (e--; e >= 0; e--)
                    if (pb->geqs[e].coef[i])
                    if (pb->geqs[e].coef[i])
                      omega_delete_geq (pb, e, n_vars);
                      omega_delete_geq (pb, e, n_vars);
 
 
                  try_again = (i < n_vars);
                  try_again = (i < n_vars);
                }
                }
 
 
              omega_delete_variable (pb, i);
              omega_delete_variable (pb, i);
              n_vars = pb->num_vars;
              n_vars = pb->num_vars;
            }
            }
        }
        }
    }
    }
 
 
  if (dump_file && (dump_flags & TDF_DETAILS))
  if (dump_file && (dump_flags & TDF_DETAILS))
    {
    {
      fprintf (dump_file, "\nafter free eliminations:\n");
      fprintf (dump_file, "\nafter free eliminations:\n");
      omega_print_problem (dump_file, pb);
      omega_print_problem (dump_file, pb);
      fprintf (dump_file, "\n");
      fprintf (dump_file, "\n");
    }
    }
}
}
 
 
/* Do free red eliminations.  */
/* Do free red eliminations.  */
 
 
static void
static void
free_red_eliminations (omega_pb pb)
free_red_eliminations (omega_pb pb)
{
{
  bool try_again = true;
  bool try_again = true;
  int i, e, e2;
  int i, e, e2;
  int n_vars = pb->num_vars;
  int n_vars = pb->num_vars;
  bool *is_red_var = XNEWVEC (bool, OMEGA_MAX_VARS);
  bool *is_red_var = XNEWVEC (bool, OMEGA_MAX_VARS);
  bool *is_dead_var = XNEWVEC (bool, OMEGA_MAX_VARS);
  bool *is_dead_var = XNEWVEC (bool, OMEGA_MAX_VARS);
  bool *is_dead_geq = XNEWVEC (bool, OMEGA_MAX_GEQS);
  bool *is_dead_geq = XNEWVEC (bool, OMEGA_MAX_GEQS);
 
 
  for (i = n_vars; i > 0; i--)
  for (i = n_vars; i > 0; i--)
    {
    {
      is_red_var[i] = false;
      is_red_var[i] = false;
      is_dead_var[i] = false;
      is_dead_var[i] = false;
    }
    }
 
 
  for (e = pb->num_geqs - 1; e >= 0; e--)
  for (e = pb->num_geqs - 1; e >= 0; e--)
    {
    {
      is_dead_geq[e] = false;
      is_dead_geq[e] = false;
 
 
      if (pb->geqs[e].color == omega_red)
      if (pb->geqs[e].color == omega_red)
        for (i = n_vars; i > 0; i--)
        for (i = n_vars; i > 0; i--)
          if (pb->geqs[e].coef[i] != 0)
          if (pb->geqs[e].coef[i] != 0)
            is_red_var[i] = true;
            is_red_var[i] = true;
    }
    }
 
 
  while (try_again)
  while (try_again)
    {
    {
      try_again = false;
      try_again = false;
      for (i = n_vars; i > 0; i--)
      for (i = n_vars; i > 0; i--)
        if (!is_red_var[i] && !is_dead_var[i])
        if (!is_red_var[i] && !is_dead_var[i])
          {
          {
            for (e = pb->num_geqs - 1; e >= 0; e--)
            for (e = pb->num_geqs - 1; e >= 0; e--)
              if (!is_dead_geq[e] && pb->geqs[e].coef[i])
              if (!is_dead_geq[e] && pb->geqs[e].coef[i])
                break;
                break;
 
 
            if (e < 0)
            if (e < 0)
              e2 = e;
              e2 = e;
            else if (pb->geqs[e].coef[i] > 0)
            else if (pb->geqs[e].coef[i] > 0)
              {
              {
                for (e2 = e - 1; e2 >= 0; e2--)
                for (e2 = e - 1; e2 >= 0; e2--)
                  if (!is_dead_geq[e2] && pb->geqs[e2].coef[i] < 0)
                  if (!is_dead_geq[e2] && pb->geqs[e2].coef[i] < 0)
                    break;
                    break;
              }
              }
            else
            else
              {
              {
                for (e2 = e - 1; e2 >= 0; e2--)
                for (e2 = e - 1; e2 >= 0; e2--)
                  if (!is_dead_geq[e2] && pb->geqs[e2].coef[i] > 0)
                  if (!is_dead_geq[e2] && pb->geqs[e2].coef[i] > 0)
                    break;
                    break;
              }
              }
 
 
            if (e2 < 0)
            if (e2 < 0)
              {
              {
                int e3;
                int e3;
                for (e3 = pb->num_subs - 1; e3 >= 0; e3--)
                for (e3 = pb->num_subs - 1; e3 >= 0; e3--)
                  if (pb->subs[e3].coef[i])
                  if (pb->subs[e3].coef[i])
                    break;
                    break;
 
 
                if (e3 >= 0)
                if (e3 >= 0)
                  continue;
                  continue;
 
 
                for (e3 = pb->num_eqs - 1; e3 >= 0; e3--)
                for (e3 = pb->num_eqs - 1; e3 >= 0; e3--)
                  if (pb->eqs[e3].coef[i])
                  if (pb->eqs[e3].coef[i])
                    break;
                    break;
 
 
                if (e3 >= 0)
                if (e3 >= 0)
                  continue;
                  continue;
 
 
                if (dump_file && (dump_flags & TDF_DETAILS))
                if (dump_file && (dump_flags & TDF_DETAILS))
                  fprintf (dump_file, "a free red elimination of %s\n",
                  fprintf (dump_file, "a free red elimination of %s\n",
                           omega_variable_to_str (pb, i));
                           omega_variable_to_str (pb, i));
 
 
                for (; e >= 0; e--)
                for (; e >= 0; e--)
                  if (pb->geqs[e].coef[i])
                  if (pb->geqs[e].coef[i])
                    is_dead_geq[e] = true;
                    is_dead_geq[e] = true;
 
 
                try_again = true;
                try_again = true;
                is_dead_var[i] = true;
                is_dead_var[i] = true;
              }
              }
          }
          }
    }
    }
 
 
  for (e = pb->num_geqs - 1; e >= 0; e--)
  for (e = pb->num_geqs - 1; e >= 0; e--)
    if (is_dead_geq[e])
    if (is_dead_geq[e])
      omega_delete_geq (pb, e, n_vars);
      omega_delete_geq (pb, e, n_vars);
 
 
  for (i = n_vars; i > 0; i--)
  for (i = n_vars; i > 0; i--)
    if (is_dead_var[i])
    if (is_dead_var[i])
      omega_delete_variable (pb, i);
      omega_delete_variable (pb, i);
 
 
  if (dump_file && (dump_flags & TDF_DETAILS))
  if (dump_file && (dump_flags & TDF_DETAILS))
    {
    {
      fprintf (dump_file, "\nafter free red eliminations:\n");
      fprintf (dump_file, "\nafter free red eliminations:\n");
      omega_print_problem (dump_file, pb);
      omega_print_problem (dump_file, pb);
      fprintf (dump_file, "\n");
      fprintf (dump_file, "\n");
    }
    }
 
 
  free (is_red_var);
  free (is_red_var);
  free (is_dead_var);
  free (is_dead_var);
  free (is_dead_geq);
  free (is_dead_geq);
}
}
 
 
/* For equation EQ of the form "0 = EQN", insert in PB two
/* For equation EQ of the form "0 = EQN", insert in PB two
   inequalities "0 <= EQN" and "0 <= -EQN".  */
   inequalities "0 <= EQN" and "0 <= -EQN".  */
 
 
void
void
omega_convert_eq_to_geqs (omega_pb pb, int eq)
omega_convert_eq_to_geqs (omega_pb pb, int eq)
{
{
  int i;
  int i;
 
 
  if (dump_file && (dump_flags & TDF_DETAILS))
  if (dump_file && (dump_flags & TDF_DETAILS))
    fprintf (dump_file, "Converting Eq to Geqs\n");
    fprintf (dump_file, "Converting Eq to Geqs\n");
 
 
  /* Insert "0 <= EQN".  */
  /* Insert "0 <= EQN".  */
  omega_copy_eqn (&pb->geqs[pb->num_geqs], &pb->eqs[eq], pb->num_vars);
  omega_copy_eqn (&pb->geqs[pb->num_geqs], &pb->eqs[eq], pb->num_vars);
  pb->geqs[pb->num_geqs].touched = 1;
  pb->geqs[pb->num_geqs].touched = 1;
  pb->num_geqs++;
  pb->num_geqs++;
 
 
  /* Insert "0 <= -EQN".  */
  /* Insert "0 <= -EQN".  */
  omega_copy_eqn (&pb->geqs[pb->num_geqs], &pb->eqs[eq], pb->num_vars);
  omega_copy_eqn (&pb->geqs[pb->num_geqs], &pb->eqs[eq], pb->num_vars);
  pb->geqs[pb->num_geqs].touched = 1;
  pb->geqs[pb->num_geqs].touched = 1;
 
 
  for (i = 0; i <= pb->num_vars; i++)
  for (i = 0; i <= pb->num_vars; i++)
    pb->geqs[pb->num_geqs].coef[i] *= -1;
    pb->geqs[pb->num_geqs].coef[i] *= -1;
 
 
  pb->num_geqs++;
  pb->num_geqs++;
 
 
  if (dump_file && (dump_flags & TDF_DETAILS))
  if (dump_file && (dump_flags & TDF_DETAILS))
    omega_print_problem (dump_file, pb);
    omega_print_problem (dump_file, pb);
}
}
 
 
/* Eliminates variable I from PB.  */
/* Eliminates variable I from PB.  */
 
 
static void
static void
omega_do_elimination (omega_pb pb, int e, int i)
omega_do_elimination (omega_pb pb, int e, int i)
{
{
  eqn sub = omega_alloc_eqns (0, 1);
  eqn sub = omega_alloc_eqns (0, 1);
  int c;
  int c;
  int n_vars = pb->num_vars;
  int n_vars = pb->num_vars;
 
 
  if (dump_file && (dump_flags & TDF_DETAILS))
  if (dump_file && (dump_flags & TDF_DETAILS))
    fprintf (dump_file, "eliminating variable %s\n",
    fprintf (dump_file, "eliminating variable %s\n",
             omega_variable_to_str (pb, i));
             omega_variable_to_str (pb, i));
 
 
  omega_copy_eqn (sub, &pb->eqs[e], pb->num_vars);
  omega_copy_eqn (sub, &pb->eqs[e], pb->num_vars);
  c = sub->coef[i];
  c = sub->coef[i];
  sub->coef[i] = 0;
  sub->coef[i] = 0;
  if (c == 1 || c == -1)
  if (c == 1 || c == -1)
    {
    {
      if (pb->eqs[e].color == omega_red)
      if (pb->eqs[e].color == omega_red)
        {
        {
          bool fB;
          bool fB;
          omega_substitute_red (pb, sub, i, c, &fB);
          omega_substitute_red (pb, sub, i, c, &fB);
          if (fB)
          if (fB)
            omega_convert_eq_to_geqs (pb, e);
            omega_convert_eq_to_geqs (pb, e);
          else
          else
            omega_delete_variable (pb, i);
            omega_delete_variable (pb, i);
        }
        }
      else
      else
        {
        {
          omega_substitute (pb, sub, i, c);
          omega_substitute (pb, sub, i, c);
          omega_delete_variable (pb, i);
          omega_delete_variable (pb, i);
        }
        }
    }
    }
  else
  else
    {
    {
      int a = abs (c);
      int a = abs (c);
      int e2 = e;
      int e2 = e;
 
 
      if (dump_file && (dump_flags & TDF_DETAILS))
      if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file, "performing non-exact elimination, c = %d\n", c);
        fprintf (dump_file, "performing non-exact elimination, c = %d\n", c);
 
 
      for (e = pb->num_eqs - 1; e >= 0; e--)
      for (e = pb->num_eqs - 1; e >= 0; e--)
        if (pb->eqs[e].coef[i])
        if (pb->eqs[e].coef[i])
          {
          {
            eqn eqn = &(pb->eqs[e]);
            eqn eqn = &(pb->eqs[e]);
            int j, k;
            int j, k;
            for (j = n_vars; j >= 0; j--)
            for (j = n_vars; j >= 0; j--)
              eqn->coef[j] *= a;
              eqn->coef[j] *= a;
            k = eqn->coef[i];
            k = eqn->coef[i];
            eqn->coef[i] = 0;
            eqn->coef[i] = 0;
            if (sub->color == omega_red)
            if (sub->color == omega_red)
              eqn->color = omega_red;
              eqn->color = omega_red;
            for (j = n_vars; j >= 0; j--)
            for (j = n_vars; j >= 0; j--)
              eqn->coef[j] -= sub->coef[j] * k / c;
              eqn->coef[j] -= sub->coef[j] * k / c;
          }
          }
 
 
      for (e = pb->num_geqs - 1; e >= 0; e--)
      for (e = pb->num_geqs - 1; e >= 0; e--)
        if (pb->geqs[e].coef[i])
        if (pb->geqs[e].coef[i])
          {
          {
            eqn eqn = &(pb->geqs[e]);
            eqn eqn = &(pb->geqs[e]);
            int j, k;
            int j, k;
 
 
            if (sub->color == omega_red)
            if (sub->color == omega_red)
              eqn->color = omega_red;
              eqn->color = omega_red;
 
 
            for (j = n_vars; j >= 0; j--)
            for (j = n_vars; j >= 0; j--)
              eqn->coef[j] *= a;
              eqn->coef[j] *= a;
 
 
            eqn->touched = 1;
            eqn->touched = 1;
            k = eqn->coef[i];
            k = eqn->coef[i];
            eqn->coef[i] = 0;
            eqn->coef[i] = 0;
 
 
            for (j = n_vars; j >= 0; j--)
            for (j = n_vars; j >= 0; j--)
              eqn->coef[j] -= sub->coef[j] * k / c;
              eqn->coef[j] -= sub->coef[j] * k / c;
 
 
          }
          }
 
 
      for (e = pb->num_subs - 1; e >= 0; e--)
      for (e = pb->num_subs - 1; e >= 0; e--)
        if (pb->subs[e].coef[i])
        if (pb->subs[e].coef[i])
          {
          {
            eqn eqn = &(pb->subs[e]);
            eqn eqn = &(pb->subs[e]);
            int j, k;
            int j, k;
            gcc_assert (0);
            gcc_assert (0);
            gcc_assert (sub->color == omega_black);
            gcc_assert (sub->color == omega_black);
            for (j = n_vars; j >= 0; j--)
            for (j = n_vars; j >= 0; j--)
              eqn->coef[j] *= a;
              eqn->coef[j] *= a;
            k = eqn->coef[i];
            k = eqn->coef[i];
            eqn->coef[i] = 0;
            eqn->coef[i] = 0;
            for (j = n_vars; j >= 0; j--)
            for (j = n_vars; j >= 0; j--)
              eqn->coef[j] -= sub->coef[j] * k / c;
              eqn->coef[j] -= sub->coef[j] * k / c;
          }
          }
 
 
      if (in_approximate_mode)
      if (in_approximate_mode)
        omega_delete_variable (pb, i);
        omega_delete_variable (pb, i);
      else
      else
        omega_convert_eq_to_geqs (pb, e2);
        omega_convert_eq_to_geqs (pb, e2);
    }
    }
 
 
  omega_free_eqns (sub, 1);
  omega_free_eqns (sub, 1);
}
}
 
 
/* Helper function for printing "sorry, no solution".  */
/* Helper function for printing "sorry, no solution".  */
 
 
static inline enum omega_result
static inline enum omega_result
omega_problem_has_no_solution (void)
omega_problem_has_no_solution (void)
{
{
  if (dump_file && (dump_flags & TDF_DETAILS))
  if (dump_file && (dump_flags & TDF_DETAILS))
    fprintf (dump_file, "\nequations have no solution \n");
    fprintf (dump_file, "\nequations have no solution \n");
 
 
  return omega_false;
  return omega_false;
}
}
 
 
/* Helper function: solve equations in PB one at a time, following the
/* Helper function: solve equations in PB one at a time, following the
   DESIRED_RES result.  */
   DESIRED_RES result.  */
 
 
static enum omega_result
static enum omega_result
omega_solve_eq (omega_pb pb, enum omega_result desired_res)
omega_solve_eq (omega_pb pb, enum omega_result desired_res)
{
{
  int i, j, e;
  int i, j, e;
  int g, g2;
  int g, g2;
  g = 0;
  g = 0;
 
 
 
 
  if (dump_file && (dump_flags & TDF_DETAILS) && pb->num_eqs > 0)
  if (dump_file && (dump_flags & TDF_DETAILS) && pb->num_eqs > 0)
    {
    {
      fprintf (dump_file, "\nomega_solve_eq (%d, %d)\n",
      fprintf (dump_file, "\nomega_solve_eq (%d, %d)\n",
               desired_res, may_be_red);
               desired_res, may_be_red);
      omega_print_problem (dump_file, pb);
      omega_print_problem (dump_file, pb);
      fprintf (dump_file, "\n");
      fprintf (dump_file, "\n");
    }
    }
 
 
  if (may_be_red)
  if (may_be_red)
    {
    {
      i = 0;
      i = 0;
      j = pb->num_eqs - 1;
      j = pb->num_eqs - 1;
 
 
      while (1)
      while (1)
        {
        {
          eqn eq;
          eqn eq;
 
 
          while (i <= j && pb->eqs[i].color == omega_red)
          while (i <= j && pb->eqs[i].color == omega_red)
            i++;
            i++;
 
 
          while (i <= j && pb->eqs[j].color == omega_black)
          while (i <= j && pb->eqs[j].color == omega_black)
            j--;
            j--;
 
 
          if (i >= j)
          if (i >= j)
            break;
            break;
 
 
          eq = omega_alloc_eqns (0, 1);
          eq = omega_alloc_eqns (0, 1);
          omega_copy_eqn (eq, &pb->eqs[i], pb->num_vars);
          omega_copy_eqn (eq, &pb->eqs[i], pb->num_vars);
          omega_copy_eqn (&pb->eqs[i], &pb->eqs[j], pb->num_vars);
          omega_copy_eqn (&pb->eqs[i], &pb->eqs[j], pb->num_vars);
          omega_copy_eqn (&pb->eqs[j], eq, pb->num_vars);
          omega_copy_eqn (&pb->eqs[j], eq, pb->num_vars);
          omega_free_eqns (eq, 1);
          omega_free_eqns (eq, 1);
          i++;
          i++;
          j--;
          j--;
        }
        }
    }
    }
 
 
  /* Eliminate all EQ equations */
  /* Eliminate all EQ equations */
  for (e = pb->num_eqs - 1; e >= 0; e--)
  for (e = pb->num_eqs - 1; e >= 0; e--)
    {
    {
      eqn eqn = &(pb->eqs[e]);
      eqn eqn = &(pb->eqs[e]);
      int sv;
      int sv;
 
 
      if (dump_file && (dump_flags & TDF_DETAILS))
      if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file, "----\n");
        fprintf (dump_file, "----\n");
 
 
      for (i = pb->num_vars; i > 0; i--)
      for (i = pb->num_vars; i > 0; i--)
        if (eqn->coef[i])
        if (eqn->coef[i])
          break;
          break;
 
 
      g = eqn->coef[i];
      g = eqn->coef[i];
 
 
      for (j = i - 1; j > 0; j--)
      for (j = i - 1; j > 0; j--)
        if (eqn->coef[j])
        if (eqn->coef[j])
          break;
          break;
 
 
      /* i is the position of last nonzero coefficient,
      /* i is the position of last nonzero coefficient,
         g is the coefficient of i,
         g is the coefficient of i,
         j is the position of next nonzero coefficient.  */
         j is the position of next nonzero coefficient.  */
 
 
      if (j == 0)
      if (j == 0)
        {
        {
          if (eqn->coef[0] % g != 0)
          if (eqn->coef[0] % g != 0)
            return omega_problem_has_no_solution ();
            return omega_problem_has_no_solution ();
 
 
          eqn->coef[0] = eqn->coef[0] / g;
          eqn->coef[0] = eqn->coef[0] / g;
          eqn->coef[i] = 1;
          eqn->coef[i] = 1;
          pb->num_eqs--;
          pb->num_eqs--;
          omega_do_elimination (pb, e, i);
          omega_do_elimination (pb, e, i);
          continue;
          continue;
        }
        }
 
 
      else if (j == -1)
      else if (j == -1)
        {
        {
          if (eqn->coef[0] != 0)
          if (eqn->coef[0] != 0)
            return omega_problem_has_no_solution ();
            return omega_problem_has_no_solution ();
 
 
          pb->num_eqs--;
          pb->num_eqs--;
          continue;
          continue;
        }
        }
 
 
      if (g < 0)
      if (g < 0)
        g = -g;
        g = -g;
 
 
      if (g == 1)
      if (g == 1)
        {
        {
          pb->num_eqs--;
          pb->num_eqs--;
          omega_do_elimination (pb, e, i);
          omega_do_elimination (pb, e, i);
        }
        }
 
 
      else
      else
        {
        {
          int k = j;
          int k = j;
          bool promotion_possible =
          bool promotion_possible =
            (omega_safe_var_p (pb, j)
            (omega_safe_var_p (pb, j)
             && pb->safe_vars + 1 == i
             && pb->safe_vars + 1 == i
             && !omega_eqn_is_red (eqn, desired_res)
             && !omega_eqn_is_red (eqn, desired_res)
             && !in_approximate_mode);
             && !in_approximate_mode);
 
 
          if (dump_file && (dump_flags & TDF_DETAILS) && promotion_possible)
          if (dump_file && (dump_flags & TDF_DETAILS) && promotion_possible)
            fprintf (dump_file, " Promotion possible\n");
            fprintf (dump_file, " Promotion possible\n");
 
 
        normalizeEQ:
        normalizeEQ:
          if (!omega_safe_var_p (pb, j))
          if (!omega_safe_var_p (pb, j))
            {
            {
              for (; g != 1 && !omega_safe_var_p (pb, j); j--)
              for (; g != 1 && !omega_safe_var_p (pb, j); j--)
                g = gcd (abs (eqn->coef[j]), g);
                g = gcd (abs (eqn->coef[j]), g);
              g2 = g;
              g2 = g;
            }
            }
          else if (!omega_safe_var_p (pb, i))
          else if (!omega_safe_var_p (pb, i))
            g2 = g;
            g2 = g;
          else
          else
            g2 = 0;
            g2 = 0;
 
 
          for (; g != 1 && j > 0; j--)
          for (; g != 1 && j > 0; j--)
            g = gcd (abs (eqn->coef[j]), g);
            g = gcd (abs (eqn->coef[j]), g);
 
 
          if (g > 1)
          if (g > 1)
            {
            {
              if (eqn->coef[0] % g != 0)
              if (eqn->coef[0] % g != 0)
                return omega_problem_has_no_solution ();
                return omega_problem_has_no_solution ();
 
 
              for (j = 0; j <= pb->num_vars; j++)
              for (j = 0; j <= pb->num_vars; j++)
                eqn->coef[j] /= g;
                eqn->coef[j] /= g;
 
 
              g2 = g2 / g;
              g2 = g2 / g;
            }
            }
 
 
          if (g2 > 1)
          if (g2 > 1)
            {
            {
              int e2;
              int e2;
 
 
              for (e2 = e - 1; e2 >= 0; e2--)
              for (e2 = e - 1; e2 >= 0; e2--)
                if (pb->eqs[e2].coef[i])
                if (pb->eqs[e2].coef[i])
                  break;
                  break;
 
 
              if (e2 == -1)
              if (e2 == -1)
                for (e2 = pb->num_geqs - 1; e2 >= 0; e2--)
                for (e2 = pb->num_geqs - 1; e2 >= 0; e2--)
                  if (pb->geqs[e2].coef[i])
                  if (pb->geqs[e2].coef[i])
                    break;
                    break;
 
 
              if (e2 == -1)
              if (e2 == -1)
                for (e2 = pb->num_subs - 1; e2 >= 0; e2--)
                for (e2 = pb->num_subs - 1; e2 >= 0; e2--)
                  if (pb->subs[e2].coef[i])
                  if (pb->subs[e2].coef[i])
                    break;
                    break;
 
 
              if (e2 == -1)
              if (e2 == -1)
                {
                {
                  bool change = false;
                  bool change = false;
 
 
                  if (dump_file && (dump_flags & TDF_DETAILS))
                  if (dump_file && (dump_flags & TDF_DETAILS))
                    {
                    {
                      fprintf (dump_file, "Ha! We own it! \n");
                      fprintf (dump_file, "Ha! We own it! \n");
                      omega_print_eq (dump_file, pb, eqn);
                      omega_print_eq (dump_file, pb, eqn);
                      fprintf (dump_file, " \n");
                      fprintf (dump_file, " \n");
                    }
                    }
 
 
                  g = eqn->coef[i];
                  g = eqn->coef[i];
                  g = abs (g);
                  g = abs (g);
 
 
                  for (j = i - 1; j >= 0; j--)
                  for (j = i - 1; j >= 0; j--)
                    {
                    {
                      int t = int_mod (eqn->coef[j], g);
                      int t = int_mod (eqn->coef[j], g);
 
 
                      if (2 * t >= g)
                      if (2 * t >= g)
                        t -= g;
                        t -= g;
 
 
                      if (t != eqn->coef[j])
                      if (t != eqn->coef[j])
                        {
                        {
                          eqn->coef[j] = t;
                          eqn->coef[j] = t;
                          change = true;
                          change = true;
                        }
                        }
                    }
                    }
 
 
                  if (!change)
                  if (!change)
                    {
                    {
                      if (dump_file && (dump_flags & TDF_DETAILS))
                      if (dump_file && (dump_flags & TDF_DETAILS))
                        fprintf (dump_file, "So what?\n");
                        fprintf (dump_file, "So what?\n");
                    }
                    }
 
 
                  else
                  else
                    {
                    {
                      omega_name_wild_card (pb, i);
                      omega_name_wild_card (pb, i);
 
 
                      if (dump_file && (dump_flags & TDF_DETAILS))
                      if (dump_file && (dump_flags & TDF_DETAILS))
                        {
                        {
                          omega_print_eq (dump_file, pb, eqn);
                          omega_print_eq (dump_file, pb, eqn);
                          fprintf (dump_file, " \n");
                          fprintf (dump_file, " \n");
                        }
                        }
 
 
                      e++;
                      e++;
                      continue;
                      continue;
                    }
                    }
                }
                }
            }
            }
 
 
          if (promotion_possible)
          if (promotion_possible)
            {
            {
              if (dump_file && (dump_flags & TDF_DETAILS))
              if (dump_file && (dump_flags & TDF_DETAILS))
                {
                {
                  fprintf (dump_file, "promoting %s to safety\n",
                  fprintf (dump_file, "promoting %s to safety\n",
                           omega_variable_to_str (pb, i));
                           omega_variable_to_str (pb, i));
                  omega_print_vars (dump_file, pb);
                  omega_print_vars (dump_file, pb);
                }
                }
 
 
              pb->safe_vars++;
              pb->safe_vars++;
 
 
              if (!omega_wildcard_p (pb, i))
              if (!omega_wildcard_p (pb, i))
                omega_name_wild_card (pb, i);
                omega_name_wild_card (pb, i);
 
 
              promotion_possible = false;
              promotion_possible = false;
              j = k;
              j = k;
              goto normalizeEQ;
              goto normalizeEQ;
            }
            }
 
 
          if (g2 > 1 && !in_approximate_mode)
          if (g2 > 1 && !in_approximate_mode)
            {
            {
              if (pb->eqs[e].color == omega_red)
              if (pb->eqs[e].color == omega_red)
                {
                {
                  if (dump_file && (dump_flags & TDF_DETAILS))
                  if (dump_file && (dump_flags & TDF_DETAILS))
                    fprintf (dump_file, "handling red equality\n");
                    fprintf (dump_file, "handling red equality\n");
 
 
                  pb->num_eqs--;
                  pb->num_eqs--;
                  omega_do_elimination (pb, e, i);
                  omega_do_elimination (pb, e, i);
                  continue;
                  continue;
                }
                }
 
 
              if (dump_file && (dump_flags & TDF_DETAILS))
              if (dump_file && (dump_flags & TDF_DETAILS))
                {
                {
                  fprintf (dump_file,
                  fprintf (dump_file,
                           "adding equation to handle safe variable \n");
                           "adding equation to handle safe variable \n");
                  omega_print_eq (dump_file, pb, eqn);
                  omega_print_eq (dump_file, pb, eqn);
                  fprintf (dump_file, "\n----\n");
                  fprintf (dump_file, "\n----\n");
                  omega_print_problem (dump_file, pb);
                  omega_print_problem (dump_file, pb);
                  fprintf (dump_file, "\n----\n");
                  fprintf (dump_file, "\n----\n");
                  fprintf (dump_file, "\n----\n");
                  fprintf (dump_file, "\n----\n");
                }
                }
 
 
              i = omega_add_new_wild_card (pb);
              i = omega_add_new_wild_card (pb);
              pb->num_eqs++;
              pb->num_eqs++;
              gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
              gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
              omega_init_eqn_zero (&pb->eqs[e + 1], pb->num_vars);
              omega_init_eqn_zero (&pb->eqs[e + 1], pb->num_vars);
              omega_copy_eqn (&pb->eqs[e + 1], eqn, pb->safe_vars);
              omega_copy_eqn (&pb->eqs[e + 1], eqn, pb->safe_vars);
 
 
              for (j = pb->num_vars; j >= 0; j--)
              for (j = pb->num_vars; j >= 0; j--)
                {
                {
                  pb->eqs[e + 1].coef[j] = int_mod (pb->eqs[e + 1].coef[j], g2);
                  pb->eqs[e + 1].coef[j] = int_mod (pb->eqs[e + 1].coef[j], g2);
 
 
                  if (2 * pb->eqs[e + 1].coef[j] >= g2)
                  if (2 * pb->eqs[e + 1].coef[j] >= g2)
                    pb->eqs[e + 1].coef[j] -= g2;
                    pb->eqs[e + 1].coef[j] -= g2;
                }
                }
 
 
              pb->eqs[e + 1].coef[i] = g2;
              pb->eqs[e + 1].coef[i] = g2;
              e += 2;
              e += 2;
 
 
              if (dump_file && (dump_flags & TDF_DETAILS))
              if (dump_file && (dump_flags & TDF_DETAILS))
                omega_print_problem (dump_file, pb);
                omega_print_problem (dump_file, pb);
 
 
              continue;
              continue;
            }
            }
 
 
          sv = pb->safe_vars;
          sv = pb->safe_vars;
          if (g2 == 0)
          if (g2 == 0)
            sv = 0;
            sv = 0;
 
 
          /* Find variable to eliminate.  */
          /* Find variable to eliminate.  */
          if (g2 > 1)
          if (g2 > 1)
            {
            {
              gcc_assert (in_approximate_mode);
              gcc_assert (in_approximate_mode);
 
 
              if (dump_file && (dump_flags & TDF_DETAILS))
              if (dump_file && (dump_flags & TDF_DETAILS))
                {
                {
                  fprintf (dump_file, "non-exact elimination: ");
                  fprintf (dump_file, "non-exact elimination: ");
                  omega_print_eq (dump_file, pb, eqn);
                  omega_print_eq (dump_file, pb, eqn);
                  fprintf (dump_file, "\n");
                  fprintf (dump_file, "\n");
                  omega_print_problem (dump_file, pb);
                  omega_print_problem (dump_file, pb);
                }
                }
 
 
              for (i = pb->num_vars; i > sv; i--)
              for (i = pb->num_vars; i > sv; i--)
                if (pb->eqs[e].coef[i] != 0)
                if (pb->eqs[e].coef[i] != 0)
                  break;
                  break;
            }
            }
          else
          else
            for (i = pb->num_vars; i > sv; i--)
            for (i = pb->num_vars; i > sv; i--)
              if (pb->eqs[e].coef[i] == 1 || pb->eqs[e].coef[i] == -1)
              if (pb->eqs[e].coef[i] == 1 || pb->eqs[e].coef[i] == -1)
                break;
                break;
 
 
          if (i > sv)
          if (i > sv)
            {
            {
              pb->num_eqs--;
              pb->num_eqs--;
              omega_do_elimination (pb, e, i);
              omega_do_elimination (pb, e, i);
 
 
              if (dump_file && (dump_flags & TDF_DETAILS) && g2 > 1)
              if (dump_file && (dump_flags & TDF_DETAILS) && g2 > 1)
                {
                {
                  fprintf (dump_file, "result of non-exact elimination:\n");
                  fprintf (dump_file, "result of non-exact elimination:\n");
                  omega_print_problem (dump_file, pb);
                  omega_print_problem (dump_file, pb);
                }
                }
            }
            }
          else
          else
            {
            {
              int factor = (INT_MAX);
              int factor = (INT_MAX);
              j = 0;
              j = 0;
 
 
              if (dump_file && (dump_flags & TDF_DETAILS))
              if (dump_file && (dump_flags & TDF_DETAILS))
                fprintf (dump_file, "doing moding\n");
                fprintf (dump_file, "doing moding\n");
 
 
              for (i = pb->num_vars; i != sv; i--)
              for (i = pb->num_vars; i != sv; i--)
                if ((pb->eqs[e].coef[i] & 1) != 0)
                if ((pb->eqs[e].coef[i] & 1) != 0)
                  {
                  {
                    j = i;
                    j = i;
                    i--;
                    i--;
 
 
                    for (; i != sv; i--)
                    for (; i != sv; i--)
                      if ((pb->eqs[e].coef[i] & 1) != 0)
                      if ((pb->eqs[e].coef[i] & 1) != 0)
                        break;
                        break;
 
 
                    break;
                    break;
                  }
                  }
 
 
              if (j != 0 && i == sv)
              if (j != 0 && i == sv)
                {
                {
                  omega_do_mod (pb, 2, e, j);
                  omega_do_mod (pb, 2, e, j);
                  e++;
                  e++;
                  continue;
                  continue;
                }
                }
 
 
              j = 0;
              j = 0;
              for (i = pb->num_vars; i != sv; i--)
              for (i = pb->num_vars; i != sv; i--)
                if (pb->eqs[e].coef[i] != 0
                if (pb->eqs[e].coef[i] != 0
                    && factor > abs (pb->eqs[e].coef[i]) + 1)
                    && factor > abs (pb->eqs[e].coef[i]) + 1)
                  {
                  {
                    factor = abs (pb->eqs[e].coef[i]) + 1;
                    factor = abs (pb->eqs[e].coef[i]) + 1;
                    j = i;
                    j = i;
                  }
                  }
 
 
              if (j == sv)
              if (j == sv)
                {
                {
                  if (dump_file && (dump_flags & TDF_DETAILS))
                  if (dump_file && (dump_flags & TDF_DETAILS))
                    fprintf (dump_file, "should not have happened\n");
                    fprintf (dump_file, "should not have happened\n");
                  gcc_assert (0);
                  gcc_assert (0);
                }
                }
 
 
              omega_do_mod (pb, factor, e, j);
              omega_do_mod (pb, factor, e, j);
              /* Go back and try this equation again.  */
              /* Go back and try this equation again.  */
              e++;
              e++;
            }
            }
        }
        }
    }
    }
 
 
  pb->num_eqs = 0;
  pb->num_eqs = 0;
  return omega_unknown;
  return omega_unknown;
}
}
 
 
/* Transform an inequation E to an equality, then solve DIFF problems
/* Transform an inequation E to an equality, then solve DIFF problems
   based on PB, and only differing by the constant part that is
   based on PB, and only differing by the constant part that is
   diminished by one, trying to figure out which of the constants
   diminished by one, trying to figure out which of the constants
   satisfies PB.    */
   satisfies PB.    */
 
 
static enum omega_result
static enum omega_result
parallel_splinter (omega_pb pb, int e, int diff,
parallel_splinter (omega_pb pb, int e, int diff,
                   enum omega_result desired_res)
                   enum omega_result desired_res)
{
{
  omega_pb tmp_problem;
  omega_pb tmp_problem;
  int i;
  int i;
 
 
  if (dump_file && (dump_flags & TDF_DETAILS))
  if (dump_file && (dump_flags & TDF_DETAILS))
    {
    {
      fprintf (dump_file, "Using parallel splintering\n");
      fprintf (dump_file, "Using parallel splintering\n");
      omega_print_problem (dump_file, pb);
      omega_print_problem (dump_file, pb);
    }
    }
 
 
  tmp_problem = XNEW (struct omega_pb_d);
  tmp_problem = XNEW (struct omega_pb_d);
  omega_copy_eqn (&pb->eqs[0], &pb->geqs[e], pb->num_vars);
  omega_copy_eqn (&pb->eqs[0], &pb->geqs[e], pb->num_vars);
  pb->num_eqs = 1;
  pb->num_eqs = 1;
 
 
  for (i = 0; i <= diff; i++)
  for (i = 0; i <= diff; i++)
    {
    {
      omega_copy_problem (tmp_problem, pb);
      omega_copy_problem (tmp_problem, pb);
 
 
      if (dump_file && (dump_flags & TDF_DETAILS))
      if (dump_file && (dump_flags & TDF_DETAILS))
        {
        {
          fprintf (dump_file, "Splinter # %i\n", i);
          fprintf (dump_file, "Splinter # %i\n", i);
          omega_print_problem (dump_file, pb);
          omega_print_problem (dump_file, pb);
        }
        }
 
 
      if (omega_solve_problem (tmp_problem, desired_res) == omega_true)
      if (omega_solve_problem (tmp_problem, desired_res) == omega_true)
        {
        {
          free (tmp_problem);
          free (tmp_problem);
          return omega_true;
          return omega_true;
        }
        }
 
 
      pb->eqs[0].coef[0]--;
      pb->eqs[0].coef[0]--;
    }
    }
 
 
  free (tmp_problem);
  free (tmp_problem);
  return omega_false;
  return omega_false;
}
}
 
 
/* Helper function: solve equations one at a time.  */
/* Helper function: solve equations one at a time.  */
 
 
static enum omega_result
static enum omega_result
omega_solve_geq (omega_pb pb, enum omega_result desired_res)
omega_solve_geq (omega_pb pb, enum omega_result desired_res)
{
{
  int i, e;
  int i, e;
  int n_vars, fv;
  int n_vars, fv;
  enum omega_result result;
  enum omega_result result;
  bool coupled_subscripts = false;
  bool coupled_subscripts = false;
  bool smoothed = false;
  bool smoothed = false;
  bool eliminate_again;
  bool eliminate_again;
  bool tried_eliminating_redundant = false;
  bool tried_eliminating_redundant = false;
 
 
  if (desired_res != omega_simplify)
  if (desired_res != omega_simplify)
    {
    {
      pb->num_subs = 0;
      pb->num_subs = 0;
      pb->safe_vars = 0;
      pb->safe_vars = 0;
    }
    }
 
 
 solve_geq_start:
 solve_geq_start:
  do {
  do {
    gcc_assert (desired_res == omega_simplify || pb->num_subs == 0);
    gcc_assert (desired_res == omega_simplify || pb->num_subs == 0);
 
 
    /* Verify that there are not too many inequalities.  */
    /* Verify that there are not too many inequalities.  */
    gcc_assert (pb->num_geqs <= OMEGA_MAX_GEQS);
    gcc_assert (pb->num_geqs <= OMEGA_MAX_GEQS);
 
 
    if (dump_file && (dump_flags & TDF_DETAILS))
    if (dump_file && (dump_flags & TDF_DETAILS))
      {
      {
        fprintf (dump_file, "\nomega_solve_geq (%d,%d):\n",
        fprintf (dump_file, "\nomega_solve_geq (%d,%d):\n",
                 desired_res, please_no_equalities_in_simplified_problems);
                 desired_res, please_no_equalities_in_simplified_problems);
        omega_print_problem (dump_file, pb);
        omega_print_problem (dump_file, pb);
        fprintf (dump_file, "\n");
        fprintf (dump_file, "\n");
      }
      }
 
 
    n_vars = pb->num_vars;
    n_vars = pb->num_vars;
 
 
    if (n_vars == 1)
    if (n_vars == 1)
      {
      {
        enum omega_eqn_color u_color = omega_black;
        enum omega_eqn_color u_color = omega_black;
        enum omega_eqn_color l_color = omega_black;
        enum omega_eqn_color l_color = omega_black;
        int upper_bound = pos_infinity;
        int upper_bound = pos_infinity;
        int lower_bound = neg_infinity;
        int lower_bound = neg_infinity;
 
 
        for (e = pb->num_geqs - 1; e >= 0; e--)
        for (e = pb->num_geqs - 1; e >= 0; e--)
          {
          {
            int a = pb->geqs[e].coef[1];
            int a = pb->geqs[e].coef[1];
            int c = pb->geqs[e].coef[0];
            int c = pb->geqs[e].coef[0];
 
 
            /* Our equation is ax + c >= 0, or ax >= -c, or c >= -ax.  */
            /* Our equation is ax + c >= 0, or ax >= -c, or c >= -ax.  */
            if (a == 0)
            if (a == 0)
              {
              {
                if (c < 0)
                if (c < 0)
                  return omega_problem_has_no_solution ();
                  return omega_problem_has_no_solution ();
              }
              }
            else if (a > 0)
            else if (a > 0)
              {
              {
                if (a != 1)
                if (a != 1)
                  c = int_div (c, a);
                  c = int_div (c, a);
 
 
                if (lower_bound < -c
                if (lower_bound < -c
                    || (lower_bound == -c
                    || (lower_bound == -c
                        && !omega_eqn_is_red (&pb->geqs[e], desired_res)))
                        && !omega_eqn_is_red (&pb->geqs[e], desired_res)))
                  {
                  {
                    lower_bound = -c;
                    lower_bound = -c;
                    l_color = pb->geqs[e].color;
                    l_color = pb->geqs[e].color;
                  }
                  }
              }
              }
            else
            else
              {
              {
                if (a != -1)
                if (a != -1)
                  c = int_div (c, -a);
                  c = int_div (c, -a);
 
 
                if (upper_bound > c
                if (upper_bound > c
                    || (upper_bound == c
                    || (upper_bound == c
                        && !omega_eqn_is_red (&pb->geqs[e], desired_res)))
                        && !omega_eqn_is_red (&pb->geqs[e], desired_res)))
                  {
                  {
                    upper_bound = c;
                    upper_bound = c;
                    u_color = pb->geqs[e].color;
                    u_color = pb->geqs[e].color;
                  }
                  }
              }
              }
          }
          }
 
 
        if (dump_file && (dump_flags & TDF_DETAILS))
        if (dump_file && (dump_flags & TDF_DETAILS))
          {
          {
            fprintf (dump_file, "upper bound = %d\n", upper_bound);
            fprintf (dump_file, "upper bound = %d\n", upper_bound);
            fprintf (dump_file, "lower bound = %d\n", lower_bound);
            fprintf (dump_file, "lower bound = %d\n", lower_bound);
          }
          }
 
 
        if (lower_bound > upper_bound)
        if (lower_bound > upper_bound)
          return omega_problem_has_no_solution ();
          return omega_problem_has_no_solution ();
 
 
        if (desired_res == omega_simplify)
        if (desired_res == omega_simplify)
          {
          {
            pb->num_geqs = 0;
            pb->num_geqs = 0;
            if (pb->safe_vars == 1)
            if (pb->safe_vars == 1)
              {
              {
 
 
                if (lower_bound == upper_bound
                if (lower_bound == upper_bound
                    && u_color == omega_black
                    && u_color == omega_black
                    && l_color == omega_black)
                    && l_color == omega_black)
                  {
                  {
                    pb->eqs[0].coef[0] = -lower_bound;
                    pb->eqs[0].coef[0] = -lower_bound;
                    pb->eqs[0].coef[1] = 1;
                    pb->eqs[0].coef[1] = 1;
                    pb->eqs[0].color = omega_black;
                    pb->eqs[0].color = omega_black;
                    pb->num_eqs = 1;
                    pb->num_eqs = 1;
                    return omega_solve_problem (pb, desired_res);
                    return omega_solve_problem (pb, desired_res);
                  }
                  }
                else
                else
                  {
                  {
                    if (lower_bound > neg_infinity)
                    if (lower_bound > neg_infinity)
                      {
                      {
                        pb->geqs[0].coef[0] = -lower_bound;
                        pb->geqs[0].coef[0] = -lower_bound;
                        pb->geqs[0].coef[1] = 1;
                        pb->geqs[0].coef[1] = 1;
                        pb->geqs[0].key = 1;
                        pb->geqs[0].key = 1;
                        pb->geqs[0].color = l_color;
                        pb->geqs[0].color = l_color;
                        pb->geqs[0].touched = 0;
                        pb->geqs[0].touched = 0;
                        pb->num_geqs = 1;
                        pb->num_geqs = 1;
                      }
                      }
 
 
                    if (upper_bound < pos_infinity)
                    if (upper_bound < pos_infinity)
                      {
                      {
                        pb->geqs[pb->num_geqs].coef[0] = upper_bound;
                        pb->geqs[pb->num_geqs].coef[0] = upper_bound;
                        pb->geqs[pb->num_geqs].coef[1] = -1;
                        pb->geqs[pb->num_geqs].coef[1] = -1;
                        pb->geqs[pb->num_geqs].key = -1;
                        pb->geqs[pb->num_geqs].key = -1;
                        pb->geqs[pb->num_geqs].color = u_color;
                        pb->geqs[pb->num_geqs].color = u_color;
                        pb->geqs[pb->num_geqs].touched = 0;
                        pb->geqs[pb->num_geqs].touched = 0;
                        pb->num_geqs++;
                        pb->num_geqs++;
                      }
                      }
                  }
                  }
              }
              }
            else
            else
              pb->num_vars = 0;
              pb->num_vars = 0;
 
 
            omega_problem_reduced (pb);
            omega_problem_reduced (pb);
            return omega_false;
            return omega_false;
          }
          }
 
 
        if (original_problem != no_problem
        if (original_problem != no_problem
            && l_color == omega_black
            && l_color == omega_black
            && u_color == omega_black
            && u_color == omega_black
            && !conservative
            && !conservative
            && lower_bound == upper_bound)
            && lower_bound == upper_bound)
          {
          {
            pb->eqs[0].coef[0] = -lower_bound;
            pb->eqs[0].coef[0] = -lower_bound;
            pb->eqs[0].coef[1] = 1;
            pb->eqs[0].coef[1] = 1;
            pb->num_eqs = 1;
            pb->num_eqs = 1;
            adding_equality_constraint (pb, 0);
            adding_equality_constraint (pb, 0);
          }
          }
 
 
        return omega_true;
        return omega_true;
      }
      }
 
 
    if (!pb->variables_freed)
    if (!pb->variables_freed)
      {
      {
        pb->variables_freed = true;
        pb->variables_freed = true;
 
 
        if (desired_res != omega_simplify)
        if (desired_res != omega_simplify)
          omega_free_eliminations (pb, 0);
          omega_free_eliminations (pb, 0);
        else
        else
          omega_free_eliminations (pb, pb->safe_vars);
          omega_free_eliminations (pb, pb->safe_vars);
 
 
        n_vars = pb->num_vars;
        n_vars = pb->num_vars;
 
 
        if (n_vars == 1)
        if (n_vars == 1)
          continue;
          continue;
      }
      }
 
 
    switch (normalize_omega_problem (pb))
    switch (normalize_omega_problem (pb))
      {
      {
      case normalize_false:
      case normalize_false:
        return omega_false;
        return omega_false;
        break;
        break;
 
 
      case normalize_coupled:
      case normalize_coupled:
        coupled_subscripts = true;
        coupled_subscripts = true;
        break;
        break;
 
 
      case normalize_uncoupled:
      case normalize_uncoupled:
        coupled_subscripts = false;
        coupled_subscripts = false;
        break;
        break;
 
 
      default:
      default:
        gcc_unreachable ();
        gcc_unreachable ();
      }
      }
 
 
    n_vars = pb->num_vars;
    n_vars = pb->num_vars;
 
 
    if (dump_file && (dump_flags & TDF_DETAILS))
    if (dump_file && (dump_flags & TDF_DETAILS))
      {
      {
        fprintf (dump_file, "\nafter normalization:\n");
        fprintf (dump_file, "\nafter normalization:\n");
        omega_print_problem (dump_file, pb);
        omega_print_problem (dump_file, pb);
        fprintf (dump_file, "\n");
        fprintf (dump_file, "\n");
        fprintf (dump_file, "eliminating variable using Fourier-Motzkin.\n");
        fprintf (dump_file, "eliminating variable using Fourier-Motzkin.\n");
      }
      }
 
 
    do {
    do {
      int parallel_difference = INT_MAX;
      int parallel_difference = INT_MAX;
      int best_parallel_eqn = -1;
      int best_parallel_eqn = -1;
      int minC, maxC, minCj = 0;
      int minC, maxC, minCj = 0;
      int lower_bound_count = 0;
      int lower_bound_count = 0;
      int e2, Le = 0, Ue;
      int e2, Le = 0, Ue;
      bool possible_easy_int_solution;
      bool possible_easy_int_solution;
      int max_splinters = 1;
      int max_splinters = 1;
      bool exact = false;
      bool exact = false;
      bool lucky_exact = false;
      bool lucky_exact = false;
      int best = (INT_MAX);
      int best = (INT_MAX);
      int j = 0, jLe = 0, jLowerBoundCount = 0;
      int j = 0, jLe = 0, jLowerBoundCount = 0;
 
 
 
 
      eliminate_again = false;
      eliminate_again = false;
 
 
      if (pb->num_eqs > 0)
      if (pb->num_eqs > 0)
        return omega_solve_problem (pb, desired_res);
        return omega_solve_problem (pb, desired_res);
 
 
      if (!coupled_subscripts)
      if (!coupled_subscripts)
        {
        {
          if (pb->safe_vars == 0)
          if (pb->safe_vars == 0)
            pb->num_geqs = 0;
            pb->num_geqs = 0;
          else
          else
            for (e = pb->num_geqs - 1; e >= 0; e--)
            for (e = pb->num_geqs - 1; e >= 0; e--)
              if (!omega_safe_var_p (pb, abs (pb->geqs[e].key)))
              if (!omega_safe_var_p (pb, abs (pb->geqs[e].key)))
                omega_delete_geq (pb, e, n_vars);
                omega_delete_geq (pb, e, n_vars);
 
 
          pb->num_vars = pb->safe_vars;
          pb->num_vars = pb->safe_vars;
 
 
          if (desired_res == omega_simplify)
          if (desired_res == omega_simplify)
            {
            {
              omega_problem_reduced (pb);
              omega_problem_reduced (pb);
              return omega_false;
              return omega_false;
            }
            }
 
 
          return omega_true;
          return omega_true;
        }
        }
 
 
      if (desired_res != omega_simplify)
      if (desired_res != omega_simplify)
        fv = 0;
        fv = 0;
      else
      else
        fv = pb->safe_vars;
        fv = pb->safe_vars;
 
 
      if (pb->num_geqs == 0)
      if (pb->num_geqs == 0)
        {
        {
          if (desired_res == omega_simplify)
          if (desired_res == omega_simplify)
            {
            {
              pb->num_vars = pb->safe_vars;
              pb->num_vars = pb->safe_vars;
              omega_problem_reduced (pb);
              omega_problem_reduced (pb);
              return omega_false;
              return omega_false;
            }
            }
          return omega_true;
          return omega_true;
        }
        }
 
 
      if (desired_res == omega_simplify && n_vars == pb->safe_vars)
      if (desired_res == omega_simplify && n_vars == pb->safe_vars)
        {
        {
          omega_problem_reduced (pb);
          omega_problem_reduced (pb);
          return omega_false;
          return omega_false;
        }
        }
 
 
      if (pb->num_geqs > OMEGA_MAX_GEQS - 30
      if (pb->num_geqs > OMEGA_MAX_GEQS - 30
          || pb->num_geqs > 2 * n_vars * n_vars + 4 * n_vars + 10)
          || pb->num_geqs > 2 * n_vars * n_vars + 4 * n_vars + 10)
        {
        {
          if (dump_file && (dump_flags & TDF_DETAILS))
          if (dump_file && (dump_flags & TDF_DETAILS))
            fprintf (dump_file,
            fprintf (dump_file,
                     "TOO MANY EQUATIONS; "
                     "TOO MANY EQUATIONS; "
                     "%d equations, %d variables, "
                     "%d equations, %d variables, "
                     "ELIMINATING REDUNDANT ONES\n",
                     "ELIMINATING REDUNDANT ONES\n",
                     pb->num_geqs, n_vars);
                     pb->num_geqs, n_vars);
 
 
          if (!omega_eliminate_redundant (pb, false))
          if (!omega_eliminate_redundant (pb, false))
            return omega_false;
            return omega_false;
 
 
          n_vars = pb->num_vars;
          n_vars = pb->num_vars;
 
 
          if (pb->num_eqs > 0)
          if (pb->num_eqs > 0)
            return omega_solve_problem (pb, desired_res);
            return omega_solve_problem (pb, desired_res);
 
 
          if (dump_file && (dump_flags & TDF_DETAILS))
          if (dump_file && (dump_flags & TDF_DETAILS))
            fprintf (dump_file, "END ELIMINATION OF REDUNDANT EQUATIONS\n");
            fprintf (dump_file, "END ELIMINATION OF REDUNDANT EQUATIONS\n");
        }
        }
 
 
      if (desired_res != omega_simplify)
      if (desired_res != omega_simplify)
        fv = 0;
        fv = 0;
      else
      else
        fv = pb->safe_vars;
        fv = pb->safe_vars;
 
 
      for (i = n_vars; i != fv; i--)
      for (i = n_vars; i != fv; i--)
        {
        {
          int score;
          int score;
          int ub = -2;
          int ub = -2;
          int lb = -2;
          int lb = -2;
          bool lucky = false;
          bool lucky = false;
          int upper_bound_count = 0;
          int upper_bound_count = 0;
 
 
          lower_bound_count = 0;
          lower_bound_count = 0;
          minC = maxC = 0;
          minC = maxC = 0;
 
 
          for (e = pb->num_geqs - 1; e >= 0; e--)
          for (e = pb->num_geqs - 1; e >= 0; e--)
            if (pb->geqs[e].coef[i] < 0)
            if (pb->geqs[e].coef[i] < 0)
              {
              {
                minC = MIN (minC, pb->geqs[e].coef[i]);
                minC = MIN (minC, pb->geqs[e].coef[i]);
                upper_bound_count++;
                upper_bound_count++;
                if (pb->geqs[e].coef[i] < -1)
                if (pb->geqs[e].coef[i] < -1)
                  {
                  {
                    if (ub == -2)
                    if (ub == -2)
                      ub = e;
                      ub = e;
                    else
                    else
                      ub = -1;
                      ub = -1;
                  }
                  }
              }
              }
            else if (pb->geqs[e].coef[i] > 0)
            else if (pb->geqs[e].coef[i] > 0)
              {
              {
                maxC = MAX (maxC, pb->geqs[e].coef[i]);
                maxC = MAX (maxC, pb->geqs[e].coef[i]);
                lower_bound_count++;
                lower_bound_count++;
                Le = e;
                Le = e;
                if (pb->geqs[e].coef[i] > 1)
                if (pb->geqs[e].coef[i] > 1)
                  {
                  {
                    if (lb == -2)
                    if (lb == -2)
                      lb = e;
                      lb = e;
                    else
                    else
                      lb = -1;
                      lb = -1;
                  }
                  }
              }
              }
 
 
          if (lower_bound_count == 0
          if (lower_bound_count == 0
              || upper_bound_count == 0)
              || upper_bound_count == 0)
            {
            {
              lower_bound_count = 0;
              lower_bound_count = 0;
              break;
              break;
            }
            }
 
 
          if (ub >= 0 && lb >= 0
          if (ub >= 0 && lb >= 0
              && pb->geqs[lb].key == -pb->geqs[ub].key)
              && pb->geqs[lb].key == -pb->geqs[ub].key)
            {
            {
              int Lc = pb->geqs[lb].coef[i];
              int Lc = pb->geqs[lb].coef[i];
              int Uc = -pb->geqs[ub].coef[i];
              int Uc = -pb->geqs[ub].coef[i];
              int diff =
              int diff =
                Lc * pb->geqs[ub].coef[0] + Uc * pb->geqs[lb].coef[0];
                Lc * pb->geqs[ub].coef[0] + Uc * pb->geqs[lb].coef[0];
              lucky = (diff >= (Uc - 1) * (Lc - 1));
              lucky = (diff >= (Uc - 1) * (Lc - 1));
            }
            }
 
 
          if (maxC == 1
          if (maxC == 1
              || minC == -1
              || minC == -1
              || lucky
              || lucky
              || in_approximate_mode)
              || in_approximate_mode)
            {
            {
              score = upper_bound_count * lower_bound_count;
              score = upper_bound_count * lower_bound_count;
 
 
              if (dump_file && (dump_flags & TDF_DETAILS))
              if (dump_file && (dump_flags & TDF_DETAILS))
                fprintf (dump_file,
                fprintf (dump_file,
                         "For %s, exact, score = %d*%d, range = %d ... %d,"
                         "For %s, exact, score = %d*%d, range = %d ... %d,"
                         "\nlucky = %d, in_approximate_mode=%d \n",
                         "\nlucky = %d, in_approximate_mode=%d \n",
                         omega_variable_to_str (pb, i),
                         omega_variable_to_str (pb, i),
                         upper_bound_count,
                         upper_bound_count,
                         lower_bound_count, minC, maxC, lucky,
                         lower_bound_count, minC, maxC, lucky,
                         in_approximate_mode);
                         in_approximate_mode);
 
 
              if (!exact
              if (!exact
                  || score < best)
                  || score < best)
                {
                {
 
 
                  best = score;
                  best = score;
                  j = i;
                  j = i;
                  minCj = minC;
                  minCj = minC;
                  jLe = Le;
                  jLe = Le;
                  jLowerBoundCount = lower_bound_count;
                  jLowerBoundCount = lower_bound_count;
                  exact = true;
                  exact = true;
                  lucky_exact = lucky;
                  lucky_exact = lucky;
                  if (score == 1)
                  if (score == 1)
                    break;
                    break;
                }
                }
            }
            }
          else if (!exact)
          else if (!exact)
            {
            {
              if (dump_file && (dump_flags & TDF_DETAILS))
              if (dump_file && (dump_flags & TDF_DETAILS))
                fprintf (dump_file,
                fprintf (dump_file,
                         "For %s, non-exact, score = %d*%d,"
                         "For %s, non-exact, score = %d*%d,"
                         "range = %d ... %d \n",
                         "range = %d ... %d \n",
                         omega_variable_to_str (pb, i),
                         omega_variable_to_str (pb, i),
                         upper_bound_count,
                         upper_bound_count,
                         lower_bound_count, minC, maxC);
                         lower_bound_count, minC, maxC);
 
 
              score = maxC - minC;
              score = maxC - minC;
 
 
              if (best > score)
              if (best > score)
                {
                {
                  best = score;
                  best = score;
                  j = i;
                  j = i;
                  minCj = minC;
                  minCj = minC;
                  jLe = Le;
                  jLe = Le;
                  jLowerBoundCount = lower_bound_count;
                  jLowerBoundCount = lower_bound_count;
                }
                }
            }
            }
        }
        }
 
 
      if (lower_bound_count == 0)
      if (lower_bound_count == 0)
        {
        {
          omega_free_eliminations (pb, pb->safe_vars);
          omega_free_eliminations (pb, pb->safe_vars);
          n_vars = pb->num_vars;
          n_vars = pb->num_vars;
          eliminate_again = true;
          eliminate_again = true;
          continue;
          continue;
        }
        }
 
 
      i = j;
      i = j;
      minC = minCj;
      minC = minCj;
      Le = jLe;
      Le = jLe;
      lower_bound_count = jLowerBoundCount;
      lower_bound_count = jLowerBoundCount;
 
 
      for (e = pb->num_geqs - 1; e >= 0; e--)
      for (e = pb->num_geqs - 1; e >= 0; e--)
        if (pb->geqs[e].coef[i] > 0)
        if (pb->geqs[e].coef[i] > 0)
          {
          {
            if (pb->geqs[e].coef[i] == -minC)
            if (pb->geqs[e].coef[i] == -minC)
              max_splinters += -minC - 1;
              max_splinters += -minC - 1;
            else
            else
              max_splinters +=
              max_splinters +=
                check_pos_mul ((pb->geqs[e].coef[i] - 1),
                check_pos_mul ((pb->geqs[e].coef[i] - 1),
                               (-minC - 1)) / (-minC) + 1;
                               (-minC - 1)) / (-minC) + 1;
          }
          }
 
 
      /* #ifdef Omega3 */
      /* #ifdef Omega3 */
      /* Trying to produce exact elimination by finding redundant
      /* Trying to produce exact elimination by finding redundant
         constraints.  */
         constraints.  */
      if (!exact && !tried_eliminating_redundant)
      if (!exact && !tried_eliminating_redundant)
        {
        {
          omega_eliminate_redundant (pb, false);
          omega_eliminate_redundant (pb, false);
          tried_eliminating_redundant = true;
          tried_eliminating_redundant = true;
          eliminate_again = true;
          eliminate_again = true;
          continue;
          continue;
        }
        }
      tried_eliminating_redundant = false;
      tried_eliminating_redundant = false;
      /* #endif */
      /* #endif */
 
 
      if (return_single_result && desired_res == omega_simplify && !exact)
      if (return_single_result && desired_res == omega_simplify && !exact)
        {
        {
          omega_problem_reduced (pb);
          omega_problem_reduced (pb);
          return omega_true;
          return omega_true;
        }
        }
 
 
      /* #ifndef Omega3 */
      /* #ifndef Omega3 */
      /* Trying to produce exact elimination by finding redundant
      /* Trying to produce exact elimination by finding redundant
         constraints.  */
         constraints.  */
      if (!exact && !tried_eliminating_redundant)
      if (!exact && !tried_eliminating_redundant)
        {
        {
          omega_eliminate_redundant (pb, false);
          omega_eliminate_redundant (pb, false);
          tried_eliminating_redundant = true;
          tried_eliminating_redundant = true;
          continue;
          continue;
        }
        }
      tried_eliminating_redundant = false;
      tried_eliminating_redundant = false;
      /* #endif */
      /* #endif */
 
 
      if (!exact)
      if (!exact)
        {
        {
          int e1, e2;
          int e1, e2;
 
 
          for (e1 = pb->num_geqs - 1; e1 >= 0; e1--)
          for (e1 = pb->num_geqs - 1; e1 >= 0; e1--)
            if (pb->geqs[e1].color == omega_black)
            if (pb->geqs[e1].color == omega_black)
              for (e2 = e1 - 1; e2 >= 0; e2--)
              for (e2 = e1 - 1; e2 >= 0; e2--)
                if (pb->geqs[e2].color == omega_black
                if (pb->geqs[e2].color == omega_black
                    && pb->geqs[e1].key == -pb->geqs[e2].key
                    && pb->geqs[e1].key == -pb->geqs[e2].key
                    && ((pb->geqs[e1].coef[0] + pb->geqs[e2].coef[0])
                    && ((pb->geqs[e1].coef[0] + pb->geqs[e2].coef[0])
                        * (3 - single_var_geq (&pb->geqs[e1], pb->num_vars))
                        * (3 - single_var_geq (&pb->geqs[e1], pb->num_vars))
                        / 2 < parallel_difference))
                        / 2 < parallel_difference))
                  {
                  {
                    parallel_difference =
                    parallel_difference =
                      (pb->geqs[e1].coef[0] + pb->geqs[e2].coef[0])
                      (pb->geqs[e1].coef[0] + pb->geqs[e2].coef[0])
                      * (3 - single_var_geq (&pb->geqs[e1], pb->num_vars))
                      * (3 - single_var_geq (&pb->geqs[e1], pb->num_vars))
                      / 2;
                      / 2;
                    best_parallel_eqn = e1;
                    best_parallel_eqn = e1;
                  }
                  }
 
 
          if (dump_file && (dump_flags & TDF_DETAILS)
          if (dump_file && (dump_flags & TDF_DETAILS)
              && best_parallel_eqn >= 0)
              && best_parallel_eqn >= 0)
            {
            {
              fprintf (dump_file,
              fprintf (dump_file,
                       "Possible parallel projection, diff = %d, in ",
                       "Possible parallel projection, diff = %d, in ",
                       parallel_difference);
                       parallel_difference);
              omega_print_geq (dump_file, pb, &(pb->geqs[best_parallel_eqn]));
              omega_print_geq (dump_file, pb, &(pb->geqs[best_parallel_eqn]));
              fprintf (dump_file, "\n");
              fprintf (dump_file, "\n");
              omega_print_problem (dump_file, pb);
              omega_print_problem (dump_file, pb);
            }
            }
        }
        }
 
 
      if (dump_file && (dump_flags & TDF_DETAILS))
      if (dump_file && (dump_flags & TDF_DETAILS))
        {
        {
          fprintf (dump_file, "going to eliminate %s, (%d,%d,%d)\n",
          fprintf (dump_file, "going to eliminate %s, (%d,%d,%d)\n",
                   omega_variable_to_str (pb, i), i, minC,
                   omega_variable_to_str (pb, i), i, minC,
                   lower_bound_count);
                   lower_bound_count);
          omega_print_problem (dump_file, pb);
          omega_print_problem (dump_file, pb);
 
 
          if (lucky_exact)
          if (lucky_exact)
            fprintf (dump_file, "(a lucky exact elimination)\n");
            fprintf (dump_file, "(a lucky exact elimination)\n");
 
 
          else if (exact)
          else if (exact)
            fprintf (dump_file, "(an exact elimination)\n");
            fprintf (dump_file, "(an exact elimination)\n");
 
 
          fprintf (dump_file, "Max # of splinters = %d\n", max_splinters);
          fprintf (dump_file, "Max # of splinters = %d\n", max_splinters);
        }
        }
 
 
      gcc_assert (max_splinters >= 1);
      gcc_assert (max_splinters >= 1);
 
 
      if (!exact && desired_res == omega_simplify && best_parallel_eqn >= 0
      if (!exact && desired_res == omega_simplify && best_parallel_eqn >= 0
          && parallel_difference <= max_splinters)
          && parallel_difference <= max_splinters)
        return parallel_splinter (pb, best_parallel_eqn, parallel_difference,
        return parallel_splinter (pb, best_parallel_eqn, parallel_difference,
                                  desired_res);
                                  desired_res);
 
 
      smoothed = false;
      smoothed = false;
 
 
      if (i != n_vars)
      if (i != n_vars)
        {
        {
          int t;
          int t;
          int j = pb->num_vars;
          int j = pb->num_vars;
 
 
          if (dump_file && (dump_flags & TDF_DETAILS))
          if (dump_file && (dump_flags & TDF_DETAILS))
            {
            {
              fprintf (dump_file, "Swapping %d and %d\n", i, j);
              fprintf (dump_file, "Swapping %d and %d\n", i, j);
              omega_print_problem (dump_file, pb);
              omega_print_problem (dump_file, pb);
            }
            }
 
 
          swap (&pb->var[i], &pb->var[j]);
          swap (&pb->var[i], &pb->var[j]);
 
 
          for (e = pb->num_geqs - 1; e >= 0; e--)
          for (e = pb->num_geqs - 1; e >= 0; e--)
            if (pb->geqs[e].coef[i] != pb->geqs[e].coef[j])
            if (pb->geqs[e].coef[i] != pb->geqs[e].coef[j])
              {
              {
                pb->geqs[e].touched = 1;
                pb->geqs[e].touched = 1;
                t = pb->geqs[e].coef[i];
                t = pb->geqs[e].coef[i];
                pb->geqs[e].coef[i] = pb->geqs[e].coef[j];
                pb->geqs[e].coef[i] = pb->geqs[e].coef[j];
                pb->geqs[e].coef[j] = t;
                pb->geqs[e].coef[j] = t;
              }
              }
 
 
          for (e = pb->num_subs - 1; e >= 0; e--)
          for (e = pb->num_subs - 1; e >= 0; e--)
            if (pb->subs[e].coef[i] != pb->subs[e].coef[j])
            if (pb->subs[e].coef[i] != pb->subs[e].coef[j])
              {
              {
                t = pb->subs[e].coef[i];
                t = pb->subs[e].coef[i];
                pb->subs[e].coef[i] = pb->subs[e].coef[j];
                pb->subs[e].coef[i] = pb->subs[e].coef[j];
                pb->subs[e].coef[j] = t;
                pb->subs[e].coef[j] = t;
              }
              }
 
 
          if (dump_file && (dump_flags & TDF_DETAILS))
          if (dump_file && (dump_flags & TDF_DETAILS))
            {
            {
              fprintf (dump_file, "Swapping complete \n");
              fprintf (dump_file, "Swapping complete \n");
              omega_print_problem (dump_file, pb);
              omega_print_problem (dump_file, pb);
              fprintf (dump_file, "\n");
              fprintf (dump_file, "\n");
            }
            }
 
 
          i = j;
          i = j;
        }
        }
 
 
      else if (dump_file && (dump_flags & TDF_DETAILS))
      else if (dump_file && (dump_flags & TDF_DETAILS))
        {
        {
          fprintf (dump_file, "No swap needed\n");
          fprintf (dump_file, "No swap needed\n");
          omega_print_problem (dump_file, pb);
          omega_print_problem (dump_file, pb);
        }
        }
 
 
      pb->num_vars--;
      pb->num_vars--;
      n_vars = pb->num_vars;
      n_vars = pb->num_vars;
 
 
      if (exact)
      if (exact)
        {
        {
          if (n_vars == 1)
          if (n_vars == 1)
            {
            {
              int upper_bound = pos_infinity;
              int upper_bound = pos_infinity;
              int lower_bound = neg_infinity;
              int lower_bound = neg_infinity;
              enum omega_eqn_color ub_color = omega_black;
              enum omega_eqn_color ub_color = omega_black;
              enum omega_eqn_color lb_color = omega_black;
              enum omega_eqn_color lb_color = omega_black;
              int topeqn = pb->num_geqs - 1;
              int topeqn = pb->num_geqs - 1;
              int Lc = pb->geqs[Le].coef[i];
              int Lc = pb->geqs[Le].coef[i];
 
 
              for (Le = topeqn; Le >= 0; Le--)
              for (Le = topeqn; Le >= 0; Le--)
                if ((Lc = pb->geqs[Le].coef[i]) == 0)
                if ((Lc = pb->geqs[Le].coef[i]) == 0)
                  {
                  {
                    if (pb->geqs[Le].coef[1] == 1)
                    if (pb->geqs[Le].coef[1] == 1)
                      {
                      {
                        int constantTerm = -pb->geqs[Le].coef[0];
                        int constantTerm = -pb->geqs[Le].coef[0];
 
 
                        if (constantTerm > lower_bound ||
                        if (constantTerm > lower_bound ||
                            (constantTerm == lower_bound &&
                            (constantTerm == lower_bound &&
                             !omega_eqn_is_red (&pb->geqs[Le], desired_res)))
                             !omega_eqn_is_red (&pb->geqs[Le], desired_res)))
                          {
                          {
                            lower_bound = constantTerm;
                            lower_bound = constantTerm;
                            lb_color = pb->geqs[Le].color;
                            lb_color = pb->geqs[Le].color;
                          }
                          }
 
 
                        if (dump_file && (dump_flags & TDF_DETAILS))
                        if (dump_file && (dump_flags & TDF_DETAILS))
                          {
                          {
                            if (pb->geqs[Le].color == omega_black)
                            if (pb->geqs[Le].color == omega_black)
                              fprintf (dump_file, " :::=> %s >= %d\n",
                              fprintf (dump_file, " :::=> %s >= %d\n",
                                       omega_variable_to_str (pb, 1),
                                       omega_variable_to_str (pb, 1),
                                       constantTerm);
                                       constantTerm);
                            else
                            else
                              fprintf (dump_file,
                              fprintf (dump_file,
                                       " :::=> [%s >= %d]\n",
                                       " :::=> [%s >= %d]\n",
                                       omega_variable_to_str (pb, 1),
                                       omega_variable_to_str (pb, 1),
                                       constantTerm);
                                       constantTerm);
                          }
                          }
                      }
                      }
                    else
                    else
                      {
                      {
                        int constantTerm = pb->geqs[Le].coef[0];
                        int constantTerm = pb->geqs[Le].coef[0];
                        if (constantTerm < upper_bound ||
                        if (constantTerm < upper_bound ||
                            (constantTerm == upper_bound
                            (constantTerm == upper_bound
                             && !omega_eqn_is_red (&pb->geqs[Le],
                             && !omega_eqn_is_red (&pb->geqs[Le],
                                                   desired_res)))
                                                   desired_res)))
                          {
                          {
                            upper_bound = constantTerm;
                            upper_bound = constantTerm;
                            ub_color = pb->geqs[Le].color;
                            ub_color = pb->geqs[Le].color;
                          }
                          }
 
 
                        if (dump_file && (dump_flags & TDF_DETAILS))
                        if (dump_file && (dump_flags & TDF_DETAILS))
                          {
                          {
                            if (pb->geqs[Le].color == omega_black)
                            if (pb->geqs[Le].color == omega_black)
                              fprintf (dump_file, " :::=> %s <= %d\n",
                              fprintf (dump_file, " :::=> %s <= %d\n",
                                       omega_variable_to_str (pb, 1),
                                       omega_variable_to_str (pb, 1),
                                       constantTerm);
                                       constantTerm);
                            else
                            else
                              fprintf (dump_file,
                              fprintf (dump_file,
                                       " :::=> [%s <= %d]\n",
                                       " :::=> [%s <= %d]\n",
                                       omega_variable_to_str (pb, 1),
                                       omega_variable_to_str (pb, 1),
                                       constantTerm);
                                       constantTerm);
                          }
                          }
                      }
                      }
                  }
                  }
                else if (Lc > 0)
                else if (Lc > 0)
                  for (Ue = topeqn; Ue >= 0; Ue--)
                  for (Ue = topeqn; Ue >= 0; Ue--)
                    if (pb->geqs[Ue].coef[i] < 0
                    if (pb->geqs[Ue].coef[i] < 0
                        && pb->geqs[Le].key != -pb->geqs[Ue].key)
                        && pb->geqs[Le].key != -pb->geqs[Ue].key)
                      {
                      {
                        int Uc = -pb->geqs[Ue].coef[i];
                        int Uc = -pb->geqs[Ue].coef[i];
                        int coefficient = pb->geqs[Ue].coef[1] * Lc
                        int coefficient = pb->geqs[Ue].coef[1] * Lc
                          + pb->geqs[Le].coef[1] * Uc;
                          + pb->geqs[Le].coef[1] * Uc;
                        int constantTerm = pb->geqs[Ue].coef[0] * Lc
                        int constantTerm = pb->geqs[Ue].coef[0] * Lc
                          + pb->geqs[Le].coef[0] * Uc;
                          + pb->geqs[Le].coef[0] * Uc;
 
 
                        if (dump_file && (dump_flags & TDF_DETAILS))
                        if (dump_file && (dump_flags & TDF_DETAILS))
                          {
                          {
                            omega_print_geq_extra (dump_file, pb,
                            omega_print_geq_extra (dump_file, pb,
                                                   &(pb->geqs[Ue]));
                                                   &(pb->geqs[Ue]));
                            fprintf (dump_file, "\n");
                            fprintf (dump_file, "\n");
                            omega_print_geq_extra (dump_file, pb,
                            omega_print_geq_extra (dump_file, pb,
                                                   &(pb->geqs[Le]));
                                                   &(pb->geqs[Le]));
                            fprintf (dump_file, "\n");
                            fprintf (dump_file, "\n");
                          }
                          }
 
 
                        if (coefficient > 0)
                        if (coefficient > 0)
                          {
                          {
                            constantTerm = -int_div (constantTerm, coefficient);
                            constantTerm = -int_div (constantTerm, coefficient);
 
 
                            if (constantTerm > lower_bound
                            if (constantTerm > lower_bound
                                || (constantTerm == lower_bound
                                || (constantTerm == lower_bound
                                    && (desired_res != omega_simplify
                                    && (desired_res != omega_simplify
                                        || (pb->geqs[Ue].color == omega_black
                                        || (pb->geqs[Ue].color == omega_black
                                            && pb->geqs[Le].color == omega_black))))
                                            && pb->geqs[Le].color == omega_black))))
                              {
                              {
                                lower_bound = constantTerm;
                                lower_bound = constantTerm;
                                lb_color = (pb->geqs[Ue].color == omega_red
                                lb_color = (pb->geqs[Ue].color == omega_red
                                            || pb->geqs[Le].color == omega_red)
                                            || pb->geqs[Le].color == omega_red)
                                  ? omega_red : omega_black;
                                  ? omega_red : omega_black;
                              }
                              }
 
 
                            if (dump_file && (dump_flags & TDF_DETAILS))
                            if (dump_file && (dump_flags & TDF_DETAILS))
                              {
                              {
                                if (pb->geqs[Ue].color == omega_red
                                if (pb->geqs[Ue].color == omega_red
                                    || pb->geqs[Le].color == omega_red)
                                    || pb->geqs[Le].color == omega_red)
                                  fprintf (dump_file,
                                  fprintf (dump_file,
                                           " ::=> [%s >= %d]\n",
                                           " ::=> [%s >= %d]\n",
                                           omega_variable_to_str (pb, 1),
                                           omega_variable_to_str (pb, 1),
                                           constantTerm);
                                           constantTerm);
                                else
                                else
                                  fprintf (dump_file,
                                  fprintf (dump_file,
                                           " ::=> %s >= %d\n",
                                           " ::=> %s >= %d\n",
                                           omega_variable_to_str (pb, 1),
                                           omega_variable_to_str (pb, 1),
                                           constantTerm);
                                           constantTerm);
                              }
                              }
                          }
                          }
                        else
                        else
                          {
                          {
                            constantTerm = int_div (constantTerm, -coefficient);
                            constantTerm = int_div (constantTerm, -coefficient);
                            if (constantTerm < upper_bound
                            if (constantTerm < upper_bound
                                || (constantTerm == upper_bound
                                || (constantTerm == upper_bound
                                    && pb->geqs[Ue].color == omega_black
                                    && pb->geqs[Ue].color == omega_black
                                    && pb->geqs[Le].color == omega_black))
                                    && pb->geqs[Le].color == omega_black))
                              {
                              {
                                upper_bound = constantTerm;
                                upper_bound = constantTerm;
                                ub_color = (pb->geqs[Ue].color == omega_red
                                ub_color = (pb->geqs[Ue].color == omega_red
                                            || pb->geqs[Le].color == omega_red)
                                            || pb->geqs[Le].color == omega_red)
                                  ? omega_red : omega_black;
                                  ? omega_red : omega_black;
                              }
                              }
 
 
                            if (dump_file
                            if (dump_file
                                && (dump_flags & TDF_DETAILS))
                                && (dump_flags & TDF_DETAILS))
                              {
                              {
                                if (pb->geqs[Ue].color == omega_red
                                if (pb->geqs[Ue].color == omega_red
                                    || pb->geqs[Le].color == omega_red)
                                    || pb->geqs[Le].color == omega_red)
                                  fprintf (dump_file,
                                  fprintf (dump_file,
                                           " ::=> [%s <= %d]\n",
                                           " ::=> [%s <= %d]\n",
                                           omega_variable_to_str (pb, 1),
                                           omega_variable_to_str (pb, 1),
                                           constantTerm);
                                           constantTerm);
                                else
                                else
                                  fprintf (dump_file,
                                  fprintf (dump_file,
                                           " ::=> %s <= %d\n",
                                           " ::=> %s <= %d\n",
                                           omega_variable_to_str (pb, 1),
                                           omega_variable_to_str (pb, 1),
                                           constantTerm);
                                           constantTerm);
                              }
                              }
                          }
                          }
                      }
                      }
 
 
              pb->num_geqs = 0;
              pb->num_geqs = 0;
 
 
              if (dump_file && (dump_flags & TDF_DETAILS))
              if (dump_file && (dump_flags & TDF_DETAILS))
                fprintf (dump_file,
                fprintf (dump_file,
                         " therefore, %c%d <= %c%s%c <= %d%c\n",
                         " therefore, %c%d <= %c%s%c <= %d%c\n",
                         lb_color == omega_red ? '[' : ' ', lower_bound,
                         lb_color == omega_red ? '[' : ' ', lower_bound,
                         (lb_color == omega_red && ub_color == omega_black)
                         (lb_color == omega_red && ub_color == omega_black)
                         ? ']' : ' ',
                         ? ']' : ' ',
                         omega_variable_to_str (pb, 1),
                         omega_variable_to_str (pb, 1),
                         (lb_color == omega_black && ub_color == omega_red)
                         (lb_color == omega_black && ub_color == omega_red)
                         ? '[' : ' ',
                         ? '[' : ' ',
                         upper_bound, ub_color == omega_red ? ']' : ' ');
                         upper_bound, ub_color == omega_red ? ']' : ' ');
 
 
              if (lower_bound > upper_bound)
              if (lower_bound > upper_bound)
                return omega_false;
                return omega_false;
 
 
              if (pb->safe_vars == 1)
              if (pb->safe_vars == 1)
                {
                {
                  if (upper_bound == lower_bound
                  if (upper_bound == lower_bound
                      && !(ub_color == omega_red || lb_color == omega_red)
                      && !(ub_color == omega_red || lb_color == omega_red)
                      && !please_no_equalities_in_simplified_problems)
                      && !please_no_equalities_in_simplified_problems)
                    {
                    {
                      pb->num_eqs++;
                      pb->num_eqs++;
                      pb->eqs[0].coef[1] = -1;
                      pb->eqs[0].coef[1] = -1;
                      pb->eqs[0].coef[0] = upper_bound;
                      pb->eqs[0].coef[0] = upper_bound;
 
 
                      if (ub_color == omega_red
                      if (ub_color == omega_red
                          || lb_color == omega_red)
                          || lb_color == omega_red)
                        pb->eqs[0].color = omega_red;
                        pb->eqs[0].color = omega_red;
 
 
                      if (desired_res == omega_simplify
                      if (desired_res == omega_simplify
                          && pb->eqs[0].color == omega_black)
                          && pb->eqs[0].color == omega_black)
                        return omega_solve_problem (pb, desired_res);
                        return omega_solve_problem (pb, desired_res);
                    }
                    }
 
 
                  if (upper_bound != pos_infinity)
                  if (upper_bound != pos_infinity)
                    {
                    {
                      pb->geqs[0].coef[1] = -1;
                      pb->geqs[0].coef[1] = -1;
                      pb->geqs[0].coef[0] = upper_bound;
                      pb->geqs[0].coef[0] = upper_bound;
                      pb->geqs[0].color = ub_color;
                      pb->geqs[0].color = ub_color;
                      pb->geqs[0].key = -1;
                      pb->geqs[0].key = -1;
                      pb->geqs[0].touched = 0;
                      pb->geqs[0].touched = 0;
                      pb->num_geqs++;
                      pb->num_geqs++;
                    }
                    }
 
 
                  if (lower_bound != neg_infinity)
                  if (lower_bound != neg_infinity)
                    {
                    {
                      pb->geqs[pb->num_geqs].coef[1] = 1;
                      pb->geqs[pb->num_geqs].coef[1] = 1;
                      pb->geqs[pb->num_geqs].coef[0] = -lower_bound;
                      pb->geqs[pb->num_geqs].coef[0] = -lower_bound;
                      pb->geqs[pb->num_geqs].color = lb_color;
                      pb->geqs[pb->num_geqs].color = lb_color;
                      pb->geqs[pb->num_geqs].key = 1;
                      pb->geqs[pb->num_geqs].key = 1;
                      pb->geqs[pb->num_geqs].touched = 0;
                      pb->geqs[pb->num_geqs].touched = 0;
                      pb->num_geqs++;
                      pb->num_geqs++;
                    }
                    }
                }
                }
 
 
              if (desired_res == omega_simplify)
              if (desired_res == omega_simplify)
                {
                {
                  omega_problem_reduced (pb);
                  omega_problem_reduced (pb);
                  return omega_false;
                  return omega_false;
                }
                }
              else
              else
                {
                {
                  if (!conservative
                  if (!conservative
                      && (desired_res != omega_simplify
                      && (desired_res != omega_simplify
                          || (lb_color == omega_black
                          || (lb_color == omega_black
                              && ub_color == omega_black))
                              && ub_color == omega_black))
                      && original_problem != no_problem
                      && original_problem != no_problem
                      && lower_bound == upper_bound)
                      && lower_bound == upper_bound)
                    {
                    {
                      for (i = original_problem->num_vars; i >= 0; i--)
                      for (i = original_problem->num_vars; i >= 0; i--)
                        if (original_problem->var[i] == pb->var[1])
                        if (original_problem->var[i] == pb->var[1])
                          break;
                          break;
 
 
                      if (i == 0)
                      if (i == 0)
                        break;
                        break;
 
 
                      e = original_problem->num_eqs++;
                      e = original_problem->num_eqs++;
                      omega_init_eqn_zero (&original_problem->eqs[e],
                      omega_init_eqn_zero (&original_problem->eqs[e],
                                           original_problem->num_vars);
                                           original_problem->num_vars);
                      original_problem->eqs[e].coef[i] = -1;
                      original_problem->eqs[e].coef[i] = -1;
                      original_problem->eqs[e].coef[0] = upper_bound;
                      original_problem->eqs[e].coef[0] = upper_bound;
 
 
                      if (dump_file && (dump_flags & TDF_DETAILS))
                      if (dump_file && (dump_flags & TDF_DETAILS))
                        {
                        {
                          fprintf (dump_file,
                          fprintf (dump_file,
                                   "adding equality %d to outer problem\n", e);
                                   "adding equality %d to outer problem\n", e);
                          omega_print_problem (dump_file, original_problem);
                          omega_print_problem (dump_file, original_problem);
                        }
                        }
                    }
                    }
                  return omega_true;
                  return omega_true;
                }
                }
            }
            }
 
 
          eliminate_again = true;
          eliminate_again = true;
 
 
          if (lower_bound_count == 1)
          if (lower_bound_count == 1)
            {
            {
              eqn lbeqn = omega_alloc_eqns (0, 1);
              eqn lbeqn = omega_alloc_eqns (0, 1);
              int Lc = pb->geqs[Le].coef[i];
              int Lc = pb->geqs[Le].coef[i];
 
 
              if (dump_file && (dump_flags & TDF_DETAILS))
              if (dump_file && (dump_flags & TDF_DETAILS))
                fprintf (dump_file, "an inplace elimination\n");
                fprintf (dump_file, "an inplace elimination\n");
 
 
              omega_copy_eqn (lbeqn, &pb->geqs[Le], (n_vars + 1));
              omega_copy_eqn (lbeqn, &pb->geqs[Le], (n_vars + 1));
              omega_delete_geq_extra (pb, Le, n_vars + 1);
              omega_delete_geq_extra (pb, Le, n_vars + 1);
 
 
              for (Ue = pb->num_geqs - 1; Ue >= 0; Ue--)
              for (Ue = pb->num_geqs - 1; Ue >= 0; Ue--)
                if (pb->geqs[Ue].coef[i] < 0)
                if (pb->geqs[Ue].coef[i] < 0)
                  {
                  {
                    if (lbeqn->key == -pb->geqs[Ue].key)
                    if (lbeqn->key == -pb->geqs[Ue].key)
                      omega_delete_geq_extra (pb, Ue, n_vars + 1);
                      omega_delete_geq_extra (pb, Ue, n_vars + 1);
                    else
                    else
                      {
                      {
                        int k;
                        int k;
                        int Uc = -pb->geqs[Ue].coef[i];
                        int Uc = -pb->geqs[Ue].coef[i];
                        pb->geqs[Ue].touched = 1;
                        pb->geqs[Ue].touched = 1;
                        eliminate_again = false;
                        eliminate_again = false;
 
 
                        if (lbeqn->color == omega_red)
                        if (lbeqn->color == omega_red)
                          pb->geqs[Ue].color = omega_red;
                          pb->geqs[Ue].color = omega_red;
 
 
                        for (k = 0; k <= n_vars; k++)
                        for (k = 0; k <= n_vars; k++)
                          pb->geqs[Ue].coef[k] =
                          pb->geqs[Ue].coef[k] =
                            check_mul (pb->geqs[Ue].coef[k], Lc) +
                            check_mul (pb->geqs[Ue].coef[k], Lc) +
                            check_mul (lbeqn->coef[k], Uc);
                            check_mul (lbeqn->coef[k], Uc);
 
 
                        if (dump_file && (dump_flags & TDF_DETAILS))
                        if (dump_file && (dump_flags & TDF_DETAILS))
                          {
                          {
                            omega_print_geq (dump_file, pb,
                            omega_print_geq (dump_file, pb,
                                             &(pb->geqs[Ue]));
                                             &(pb->geqs[Ue]));
                            fprintf (dump_file, "\n");
                            fprintf (dump_file, "\n");
                          }
                          }
                      }
                      }
                  }
                  }
 
 
              omega_free_eqns (lbeqn, 1);
              omega_free_eqns (lbeqn, 1);
              continue;
              continue;
            }
            }
          else
          else
            {
            {
              int *dead_eqns = XNEWVEC (int, OMEGA_MAX_GEQS);
              int *dead_eqns = XNEWVEC (int, OMEGA_MAX_GEQS);
              bool *is_dead = XNEWVEC (bool, OMEGA_MAX_GEQS);
              bool *is_dead = XNEWVEC (bool, OMEGA_MAX_GEQS);
              int num_dead = 0;
              int num_dead = 0;
              int top_eqn = pb->num_geqs - 1;
              int top_eqn = pb->num_geqs - 1;
              lower_bound_count--;
              lower_bound_count--;
 
 
              if (dump_file && (dump_flags & TDF_DETAILS))
              if (dump_file && (dump_flags & TDF_DETAILS))
                fprintf (dump_file, "lower bound count = %d\n",
                fprintf (dump_file, "lower bound count = %d\n",
                         lower_bound_count);
                         lower_bound_count);
 
 
              for (Le = top_eqn; Le >= 0; Le--)
              for (Le = top_eqn; Le >= 0; Le--)
                if (pb->geqs[Le].coef[i] > 0)
                if (pb->geqs[Le].coef[i] > 0)
                  {
                  {
                    int Lc = pb->geqs[Le].coef[i];
                    int Lc = pb->geqs[Le].coef[i];
                    for (Ue = top_eqn; Ue >= 0; Ue--)
                    for (Ue = top_eqn; Ue >= 0; Ue--)
                      if (pb->geqs[Ue].coef[i] < 0)
                      if (pb->geqs[Ue].coef[i] < 0)
                        {
                        {
                          if (pb->geqs[Le].key != -pb->geqs[Ue].key)
                          if (pb->geqs[Le].key != -pb->geqs[Ue].key)
                            {
                            {
                              int k;
                              int k;
                              int Uc = -pb->geqs[Ue].coef[i];
                              int Uc = -pb->geqs[Ue].coef[i];
 
 
                              if (num_dead == 0)
                              if (num_dead == 0)
                                e2 = pb->num_geqs++;
                                e2 = pb->num_geqs++;
                              else
                              else
                                e2 = dead_eqns[--num_dead];
                                e2 = dead_eqns[--num_dead];
 
 
                              gcc_assert (e2 < OMEGA_MAX_GEQS);
                              gcc_assert (e2 < OMEGA_MAX_GEQS);
 
 
                              if (dump_file && (dump_flags & TDF_DETAILS))
                              if (dump_file && (dump_flags & TDF_DETAILS))
                                {
                                {
                                  fprintf (dump_file,
                                  fprintf (dump_file,
                                           "Le = %d, Ue = %d, gen = %d\n",
                                           "Le = %d, Ue = %d, gen = %d\n",
                                           Le, Ue, e2);
                                           Le, Ue, e2);
                                  omega_print_geq_extra (dump_file, pb,
                                  omega_print_geq_extra (dump_file, pb,
                                                         &(pb->geqs[Le]));
                                                         &(pb->geqs[Le]));
                                  fprintf (dump_file, "\n");
                                  fprintf (dump_file, "\n");
                                  omega_print_geq_extra (dump_file, pb,
                                  omega_print_geq_extra (dump_file, pb,
                                                         &(pb->geqs[Ue]));
                                                         &(pb->geqs[Ue]));
                                  fprintf (dump_file, "\n");
                                  fprintf (dump_file, "\n");
                                }
                                }
 
 
                              eliminate_again = false;
                              eliminate_again = false;
 
 
                              for (k = n_vars; k >= 0; k--)
                              for (k = n_vars; k >= 0; k--)
                                pb->geqs[e2].coef[k] =
                                pb->geqs[e2].coef[k] =
                                  check_mul (pb->geqs[Ue].coef[k], Lc) +
                                  check_mul (pb->geqs[Ue].coef[k], Lc) +
                                  check_mul (pb->geqs[Le].coef[k], Uc);
                                  check_mul (pb->geqs[Le].coef[k], Uc);
 
 
                              pb->geqs[e2].coef[n_vars + 1] = 0;
                              pb->geqs[e2].coef[n_vars + 1] = 0;
                              pb->geqs[e2].touched = 1;
                              pb->geqs[e2].touched = 1;
 
 
                              if (pb->geqs[Ue].color == omega_red
                              if (pb->geqs[Ue].color == omega_red
                                  || pb->geqs[Le].color == omega_red)
                                  || pb->geqs[Le].color == omega_red)
                                pb->geqs[e2].color = omega_red;
                                pb->geqs[e2].color = omega_red;
                              else
                              else
                                pb->geqs[e2].color = omega_black;
                                pb->geqs[e2].color = omega_black;
 
 
                              if (dump_file && (dump_flags & TDF_DETAILS))
                              if (dump_file && (dump_flags & TDF_DETAILS))
                                {
                                {
                                  omega_print_geq (dump_file, pb,
                                  omega_print_geq (dump_file, pb,
                                                   &(pb->geqs[e2]));
                                                   &(pb->geqs[e2]));
                                  fprintf (dump_file, "\n");
                                  fprintf (dump_file, "\n");
                                }
                                }
                            }
                            }
 
 
                          if (lower_bound_count == 0)
                          if (lower_bound_count == 0)
                            {
                            {
                              dead_eqns[num_dead++] = Ue;
                              dead_eqns[num_dead++] = Ue;
 
 
                              if (dump_file && (dump_flags & TDF_DETAILS))
                              if (dump_file && (dump_flags & TDF_DETAILS))
                                fprintf (dump_file, "Killed %d\n", Ue);
                                fprintf (dump_file, "Killed %d\n", Ue);
                            }
                            }
                        }
                        }
 
 
                    lower_bound_count--;
                    lower_bound_count--;
                    dead_eqns[num_dead++] = Le;
                    dead_eqns[num_dead++] = Le;
 
 
                    if (dump_file && (dump_flags & TDF_DETAILS))
                    if (dump_file && (dump_flags & TDF_DETAILS))
                      fprintf (dump_file, "Killed %d\n", Le);
                      fprintf (dump_file, "Killed %d\n", Le);
                  }
                  }
 
 
              for (e = pb->num_geqs - 1; e >= 0; e--)
              for (e = pb->num_geqs - 1; e >= 0; e--)
                is_dead[e] = false;
                is_dead[e] = false;
 
 
              while (num_dead > 0)
              while (num_dead > 0)
                is_dead[dead_eqns[--num_dead]] = true;
                is_dead[dead_eqns[--num_dead]] = true;
 
 
              for (e = pb->num_geqs - 1; e >= 0; e--)
              for (e = pb->num_geqs - 1; e >= 0; e--)
                if (is_dead[e])
                if (is_dead[e])
                  omega_delete_geq_extra (pb, e, n_vars + 1);
                  omega_delete_geq_extra (pb, e, n_vars + 1);
 
 
              free (dead_eqns);
              free (dead_eqns);
              free (is_dead);
              free (is_dead);
              continue;
              continue;
            }
            }
        }
        }
      else
      else
        {
        {
          omega_pb rS, iS;
          omega_pb rS, iS;
 
 
          rS = omega_alloc_problem (0, 0);
          rS = omega_alloc_problem (0, 0);
          iS = omega_alloc_problem (0, 0);
          iS = omega_alloc_problem (0, 0);
          e2 = 0;
          e2 = 0;
          possible_easy_int_solution = true;
          possible_easy_int_solution = true;
 
 
          for (e = 0; e < pb->num_geqs; e++)
          for (e = 0; e < pb->num_geqs; e++)
            if (pb->geqs[e].coef[i] == 0)
            if (pb->geqs[e].coef[i] == 0)
              {
              {
                omega_copy_eqn (&(rS->geqs[e2]), &pb->geqs[e],
                omega_copy_eqn (&(rS->geqs[e2]), &pb->geqs[e],
                                pb->num_vars);
                                pb->num_vars);
                omega_copy_eqn (&(iS->geqs[e2]), &pb->geqs[e],
                omega_copy_eqn (&(iS->geqs[e2]), &pb->geqs[e],
                                pb->num_vars);
                                pb->num_vars);
 
 
                if (dump_file && (dump_flags & TDF_DETAILS))
                if (dump_file && (dump_flags & TDF_DETAILS))
                  {
                  {
                    int t;
                    int t;
                    fprintf (dump_file, "Copying (%d, %d): ", i,
                    fprintf (dump_file, "Copying (%d, %d): ", i,
                             pb->geqs[e].coef[i]);
                             pb->geqs[e].coef[i]);
                    omega_print_geq_extra (dump_file, pb, &pb->geqs[e]);
                    omega_print_geq_extra (dump_file, pb, &pb->geqs[e]);
                    fprintf (dump_file, "\n");
                    fprintf (dump_file, "\n");
                    for (t = 0; t <= n_vars + 1; t++)
                    for (t = 0; t <= n_vars + 1; t++)
                      fprintf (dump_file, "%d ", pb->geqs[e].coef[t]);
                      fprintf (dump_file, "%d ", pb->geqs[e].coef[t]);
                    fprintf (dump_file, "\n");
                    fprintf (dump_file, "\n");
 
 
                  }
                  }
                e2++;
                e2++;
                gcc_assert (e2 < OMEGA_MAX_GEQS);
                gcc_assert (e2 < OMEGA_MAX_GEQS);
              }
              }
 
 
          for (Le = pb->num_geqs - 1; Le >= 0; Le--)
          for (Le = pb->num_geqs - 1; Le >= 0; Le--)
            if (pb->geqs[Le].coef[i] > 0)
            if (pb->geqs[Le].coef[i] > 0)
              for (Ue = pb->num_geqs - 1; Ue >= 0; Ue--)
              for (Ue = pb->num_geqs - 1; Ue >= 0; Ue--)
                if (pb->geqs[Ue].coef[i] < 0)
                if (pb->geqs[Ue].coef[i] < 0)
                  {
                  {
                    int k;
                    int k;
                    int Lc = pb->geqs[Le].coef[i];
                    int Lc = pb->geqs[Le].coef[i];
                    int Uc = -pb->geqs[Ue].coef[i];
                    int Uc = -pb->geqs[Ue].coef[i];
 
 
                    if (pb->geqs[Le].key != -pb->geqs[Ue].key)
                    if (pb->geqs[Le].key != -pb->geqs[Ue].key)
                      {
                      {
 
 
                        rS->geqs[e2].touched = iS->geqs[e2].touched = 1;
                        rS->geqs[e2].touched = iS->geqs[e2].touched = 1;
 
 
                        if (dump_file && (dump_flags & TDF_DETAILS))
                        if (dump_file && (dump_flags & TDF_DETAILS))
                          {
                          {
                            fprintf (dump_file, "---\n");
                            fprintf (dump_file, "---\n");
                            fprintf (dump_file,
                            fprintf (dump_file,
                                     "Le(Lc) = %d(%d_, Ue(Uc) = %d(%d), gen = %d\n",
                                     "Le(Lc) = %d(%d_, Ue(Uc) = %d(%d), gen = %d\n",
                                     Le, Lc, Ue, Uc, e2);
                                     Le, Lc, Ue, Uc, e2);
                            omega_print_geq_extra (dump_file, pb, &pb->geqs[Le]);
                            omega_print_geq_extra (dump_file, pb, &pb->geqs[Le]);
                            fprintf (dump_file, "\n");
                            fprintf (dump_file, "\n");
                            omega_print_geq_extra (dump_file, pb, &pb->geqs[Ue]);
                            omega_print_geq_extra (dump_file, pb, &pb->geqs[Ue]);
                            fprintf (dump_file, "\n");
                            fprintf (dump_file, "\n");
                          }
                          }
 
 
                        if (Uc == Lc)
                        if (Uc == Lc)
                          {
                          {
                            for (k = n_vars; k >= 0; k--)
                            for (k = n_vars; k >= 0; k--)
                              iS->geqs[e2].coef[k] = rS->geqs[e2].coef[k] =
                              iS->geqs[e2].coef[k] = rS->geqs[e2].coef[k] =
                                pb->geqs[Ue].coef[k] + pb->geqs[Le].coef[k];
                                pb->geqs[Ue].coef[k] + pb->geqs[Le].coef[k];
 
 
                            iS->geqs[e2].coef[0] -= (Uc - 1);
                            iS->geqs[e2].coef[0] -= (Uc - 1);
                          }
                          }
                        else
                        else
                          {
                          {
                            for (k = n_vars; k >= 0; k--)
                            for (k = n_vars; k >= 0; k--)
                              iS->geqs[e2].coef[k] = rS->geqs[e2].coef[k] =
                              iS->geqs[e2].coef[k] = rS->geqs[e2].coef[k] =
                                check_mul (pb->geqs[Ue].coef[k], Lc) +
                                check_mul (pb->geqs[Ue].coef[k], Lc) +
                                check_mul (pb->geqs[Le].coef[k], Uc);
                                check_mul (pb->geqs[Le].coef[k], Uc);
 
 
                            iS->geqs[e2].coef[0] -= (Uc - 1) * (Lc - 1);
                            iS->geqs[e2].coef[0] -= (Uc - 1) * (Lc - 1);
                          }
                          }
 
 
                        if (pb->geqs[Ue].color == omega_red
                        if (pb->geqs[Ue].color == omega_red
                            || pb->geqs[Le].color == omega_red)
                            || pb->geqs[Le].color == omega_red)
                          iS->geqs[e2].color = rS->geqs[e2].color = omega_red;
                          iS->geqs[e2].color = rS->geqs[e2].color = omega_red;
                        else
                        else
                          iS->geqs[e2].color = rS->geqs[e2].color = omega_black;
                          iS->geqs[e2].color = rS->geqs[e2].color = omega_black;
 
 
                        if (dump_file && (dump_flags & TDF_DETAILS))
                        if (dump_file && (dump_flags & TDF_DETAILS))
                          {
                          {
                            omega_print_geq (dump_file, pb, &(rS->geqs[e2]));
                            omega_print_geq (dump_file, pb, &(rS->geqs[e2]));
                            fprintf (dump_file, "\n");
                            fprintf (dump_file, "\n");
                          }
                          }
 
 
                        e2++;
                        e2++;
                        gcc_assert (e2 < OMEGA_MAX_GEQS);
                        gcc_assert (e2 < OMEGA_MAX_GEQS);
                      }
                      }
                    else if (pb->geqs[Ue].coef[0] * Lc +
                    else if (pb->geqs[Ue].coef[0] * Lc +
                             pb->geqs[Le].coef[0] * Uc -
                             pb->geqs[Le].coef[0] * Uc -
                             (Uc - 1) * (Lc - 1) < 0)
                             (Uc - 1) * (Lc - 1) < 0)
                      possible_easy_int_solution = false;
                      possible_easy_int_solution = false;
                  }
                  }
 
 
          iS->variables_initialized = rS->variables_initialized = true;
          iS->variables_initialized = rS->variables_initialized = true;
          iS->num_vars = rS->num_vars = pb->num_vars;
          iS->num_vars = rS->num_vars = pb->num_vars;
          iS->num_geqs = rS->num_geqs = e2;
          iS->num_geqs = rS->num_geqs = e2;
          iS->num_eqs = rS->num_eqs = 0;
          iS->num_eqs = rS->num_eqs = 0;
          iS->num_subs = rS->num_subs = pb->num_subs;
          iS->num_subs = rS->num_subs = pb->num_subs;
          iS->safe_vars = rS->safe_vars = pb->safe_vars;
          iS->safe_vars = rS->safe_vars = pb->safe_vars;
 
 
          for (e = n_vars; e >= 0; e--)
          for (e = n_vars; e >= 0; e--)
            rS->var[e] = pb->var[e];
            rS->var[e] = pb->var[e];
 
 
          for (e = n_vars; e >= 0; e--)
          for (e = n_vars; e >= 0; e--)
            iS->var[e] = pb->var[e];
            iS->var[e] = pb->var[e];
 
 
          for (e = pb->num_subs - 1; e >= 0; e--)
          for (e = pb->num_subs - 1; e >= 0; e--)
            {
            {
              omega_copy_eqn (&(rS->subs[e]), &(pb->subs[e]), pb->num_vars);
              omega_copy_eqn (&(rS->subs[e]), &(pb->subs[e]), pb->num_vars);
              omega_copy_eqn (&(iS->subs[e]), &(pb->subs[e]), pb->num_vars);
              omega_copy_eqn (&(iS->subs[e]), &(pb->subs[e]), pb->num_vars);
            }
            }
 
 
          pb->num_vars++;
          pb->num_vars++;
          n_vars = pb->num_vars;
          n_vars = pb->num_vars;
 
 
          if (desired_res != omega_true)
          if (desired_res != omega_true)
            {
            {
              if (original_problem == no_problem)
              if (original_problem == no_problem)
                {
                {
                  original_problem = pb;
                  original_problem = pb;
                  result = omega_solve_geq (rS, omega_false);
                  result = omega_solve_geq (rS, omega_false);
                  original_problem = no_problem;
                  original_problem = no_problem;
                }
                }
              else
              else
                result = omega_solve_geq (rS, omega_false);
                result = omega_solve_geq (rS, omega_false);
 
 
              if (result == omega_false)
              if (result == omega_false)
                {
                {
                  free (rS);
                  free (rS);
                  free (iS);
                  free (iS);
                  return result;
                  return result;
                }
                }
 
 
              if (pb->num_eqs > 0)
              if (pb->num_eqs > 0)
                {
                {
                  /* An equality constraint must have been found */
                  /* An equality constraint must have been found */
                  free (rS);
                  free (rS);
                  free (iS);
                  free (iS);
                  return omega_solve_problem (pb, desired_res);
                  return omega_solve_problem (pb, desired_res);
                }
                }
            }
            }
 
 
          if (desired_res != omega_false)
          if (desired_res != omega_false)
            {
            {
              int j;
              int j;
              int lower_bounds = 0;
              int lower_bounds = 0;
              int *lower_bound = XNEWVEC (int, OMEGA_MAX_GEQS);
              int *lower_bound = XNEWVEC (int, OMEGA_MAX_GEQS);
 
 
              if (possible_easy_int_solution)
              if (possible_easy_int_solution)
                {
                {
                  conservative++;
                  conservative++;
                  result = omega_solve_geq (iS, desired_res);
                  result = omega_solve_geq (iS, desired_res);
                  conservative--;
                  conservative--;
 
 
                  if (result != omega_false)
                  if (result != omega_false)
                    {
                    {
                      free (rS);
                      free (rS);
                      free (iS);
                      free (iS);
                      free (lower_bound);
                      free (lower_bound);
                      return result;
                      return result;
                    }
                    }
                }
                }
 
 
              if (!exact && best_parallel_eqn >= 0
              if (!exact && best_parallel_eqn >= 0
                  && parallel_difference <= max_splinters)
                  && parallel_difference <= max_splinters)
                {
                {
                  free (rS);
                  free (rS);
                  free (iS);
                  free (iS);
                  free (lower_bound);
                  free (lower_bound);
                  return parallel_splinter (pb, best_parallel_eqn,
                  return parallel_splinter (pb, best_parallel_eqn,
                                            parallel_difference,
                                            parallel_difference,
                                            desired_res);
                                            desired_res);
                }
                }
 
 
              if (dump_file && (dump_flags & TDF_DETAILS))
              if (dump_file && (dump_flags & TDF_DETAILS))
                fprintf (dump_file, "have to do exact analysis\n");
                fprintf (dump_file, "have to do exact analysis\n");
 
 
              conservative++;
              conservative++;
 
 
              for (e = 0; e < pb->num_geqs; e++)
              for (e = 0; e < pb->num_geqs; e++)
                if (pb->geqs[e].coef[i] > 1)
                if (pb->geqs[e].coef[i] > 1)
                  lower_bound[lower_bounds++] = e;
                  lower_bound[lower_bounds++] = e;
 
 
              /* Sort array LOWER_BOUND.  */
              /* Sort array LOWER_BOUND.  */
              for (j = 0; j < lower_bounds; j++)
              for (j = 0; j < lower_bounds; j++)
                {
                {
                  int k, smallest = j;
                  int k, smallest = j;
 
 
                  for (k = j + 1; k < lower_bounds; k++)
                  for (k = j + 1; k < lower_bounds; k++)
                    if (pb->geqs[lower_bound[smallest]].coef[i] >
                    if (pb->geqs[lower_bound[smallest]].coef[i] >
                        pb->geqs[lower_bound[k]].coef[i])
                        pb->geqs[lower_bound[k]].coef[i])
                      smallest = k;
                      smallest = k;
 
 
                  k = lower_bound[smallest];
                  k = lower_bound[smallest];
                  lower_bound[smallest] = lower_bound[j];
                  lower_bound[smallest] = lower_bound[j];
                  lower_bound[j] = k;
                  lower_bound[j] = k;
                }
                }
 
 
              if (dump_file && (dump_flags & TDF_DETAILS))
              if (dump_file && (dump_flags & TDF_DETAILS))
                {
                {
                  fprintf (dump_file, "lower bound coefficients = ");
                  fprintf (dump_file, "lower bound coefficients = ");
 
 
                  for (j = 0; j < lower_bounds; j++)
                  for (j = 0; j < lower_bounds; j++)
                    fprintf (dump_file, " %d",
                    fprintf (dump_file, " %d",
                             pb->geqs[lower_bound[j]].coef[i]);
                             pb->geqs[lower_bound[j]].coef[i]);
 
 
                  fprintf (dump_file, "\n");
                  fprintf (dump_file, "\n");
                }
                }
 
 
              for (j = 0; j < lower_bounds; j++)
              for (j = 0; j < lower_bounds; j++)
                {
                {
                  int max_incr;
                  int max_incr;
                  int c;
                  int c;
                  int worst_lower_bound_constant = -minC;
                  int worst_lower_bound_constant = -minC;
 
 
                  e = lower_bound[j];
                  e = lower_bound[j];
                  max_incr = (((pb->geqs[e].coef[i] - 1) *
                  max_incr = (((pb->geqs[e].coef[i] - 1) *
                               (worst_lower_bound_constant - 1) - 1)
                               (worst_lower_bound_constant - 1) - 1)
                              / worst_lower_bound_constant);
                              / worst_lower_bound_constant);
                  /* max_incr += 2; */
                  /* max_incr += 2; */
 
 
                  if (dump_file && (dump_flags & TDF_DETAILS))
                  if (dump_file && (dump_flags & TDF_DETAILS))
                    {
                    {
                      fprintf (dump_file, "for equation ");
                      fprintf (dump_file, "for equation ");
                      omega_print_geq (dump_file, pb, &pb->geqs[e]);
                      omega_print_geq (dump_file, pb, &pb->geqs[e]);
                      fprintf (dump_file,
                      fprintf (dump_file,
                               "\ntry decrements from 0 to %d\n",
                               "\ntry decrements from 0 to %d\n",
                               max_incr);
                               max_incr);
                      omega_print_problem (dump_file, pb);
                      omega_print_problem (dump_file, pb);
                    }
                    }
 
 
                  if (max_incr > 50 && !smoothed
                  if (max_incr > 50 && !smoothed
                      && smooth_weird_equations (pb))
                      && smooth_weird_equations (pb))
                    {
                    {
                      conservative--;
                      conservative--;
                      free (rS);
                      free (rS);
                      free (iS);
                      free (iS);
                      smoothed = true;
                      smoothed = true;
                      goto solve_geq_start;
                      goto solve_geq_start;
                    }
                    }
 
 
                  omega_copy_eqn (&pb->eqs[0], &pb->geqs[e],
                  omega_copy_eqn (&pb->eqs[0], &pb->geqs[e],
                                  pb->num_vars);
                                  pb->num_vars);
                  pb->eqs[0].color = omega_black;
                  pb->eqs[0].color = omega_black;
                  omega_init_eqn_zero (&pb->geqs[e], pb->num_vars);
                  omega_init_eqn_zero (&pb->geqs[e], pb->num_vars);
                  pb->geqs[e].touched = 1;
                  pb->geqs[e].touched = 1;
                  pb->num_eqs = 1;
                  pb->num_eqs = 1;
 
 
                  for (c = max_incr; c >= 0; c--)
                  for (c = max_incr; c >= 0; c--)
                    {
                    {
                      if (dump_file && (dump_flags & TDF_DETAILS))
                      if (dump_file && (dump_flags & TDF_DETAILS))
                        {
                        {
                          fprintf (dump_file,
                          fprintf (dump_file,
                                   "trying next decrement of %d\n",
                                   "trying next decrement of %d\n",
                                   max_incr - c);
                                   max_incr - c);
                          omega_print_problem (dump_file, pb);
                          omega_print_problem (dump_file, pb);
                        }
                        }
 
 
                      omega_copy_problem (rS, pb);
                      omega_copy_problem (rS, pb);
 
 
                      if (dump_file && (dump_flags & TDF_DETAILS))
                      if (dump_file && (dump_flags & TDF_DETAILS))
                        omega_print_problem (dump_file, rS);
                        omega_print_problem (dump_file, rS);
 
 
                      result = omega_solve_problem (rS, desired_res);
                      result = omega_solve_problem (rS, desired_res);
 
 
                      if (result == omega_true)
                      if (result == omega_true)
                        {
                        {
                          free (rS);
                          free (rS);
                          free (iS);
                          free (iS);
                          free (lower_bound);
                          free (lower_bound);
                          conservative--;
                          conservative--;
                          return omega_true;
                          return omega_true;
                        }
                        }
 
 
                      pb->eqs[0].coef[0]--;
                      pb->eqs[0].coef[0]--;
                    }
                    }
 
 
                  if (j + 1 < lower_bounds)
                  if (j + 1 < lower_bounds)
                    {
                    {
                      pb->num_eqs = 0;
                      pb->num_eqs = 0;
                      omega_copy_eqn (&pb->geqs[e], &pb->eqs[0],
                      omega_copy_eqn (&pb->geqs[e], &pb->eqs[0],
                                      pb->num_vars);
                                      pb->num_vars);
                      pb->geqs[e].touched = 1;
                      pb->geqs[e].touched = 1;
                      pb->geqs[e].color = omega_black;
                      pb->geqs[e].color = omega_black;
                      omega_copy_problem (rS, pb);
                      omega_copy_problem (rS, pb);
 
 
                      if (dump_file && (dump_flags & TDF_DETAILS))
                      if (dump_file && (dump_flags & TDF_DETAILS))
                        fprintf (dump_file,
                        fprintf (dump_file,
                                 "exhausted lower bound, "
                                 "exhausted lower bound, "
                                 "checking if still feasible ");
                                 "checking if still feasible ");
 
 
                      result = omega_solve_problem (rS, omega_false);
                      result = omega_solve_problem (rS, omega_false);
 
 
                      if (result == omega_false)
                      if (result == omega_false)
                        break;
                        break;
                    }
                    }
                }
                }
 
 
              if (dump_file && (dump_flags & TDF_DETAILS))
              if (dump_file && (dump_flags & TDF_DETAILS))
                fprintf (dump_file, "fall-off the end\n");
                fprintf (dump_file, "fall-off the end\n");
 
 
              free (rS);
              free (rS);
              free (iS);
              free (iS);
              free (lower_bound);
              free (lower_bound);
              conservative--;
              conservative--;
              return omega_false;
              return omega_false;
            }
            }
 
 
          free (rS);
          free (rS);
          free (iS);
          free (iS);
        }
        }
      return omega_unknown;
      return omega_unknown;
    } while (eliminate_again);
    } while (eliminate_again);
  } while (1);
  } while (1);
}
}
 
 
/* Because the omega solver is recursive, this counter limits the
/* Because the omega solver is recursive, this counter limits the
   recursion depth.  */
   recursion depth.  */
static int omega_solve_depth = 0;
static int omega_solve_depth = 0;
 
 
/* Return omega_true when the problem PB has a solution following the
/* Return omega_true when the problem PB has a solution following the
   DESIRED_RES.  */
   DESIRED_RES.  */
 
 
enum omega_result
enum omega_result
omega_solve_problem (omega_pb pb, enum omega_result desired_res)
omega_solve_problem (omega_pb pb, enum omega_result desired_res)
{
{
  enum omega_result result;
  enum omega_result result;
 
 
  gcc_assert (pb->num_vars >= pb->safe_vars);
  gcc_assert (pb->num_vars >= pb->safe_vars);
  omega_solve_depth++;
  omega_solve_depth++;
 
 
  if (desired_res != omega_simplify)
  if (desired_res != omega_simplify)
    pb->safe_vars = 0;
    pb->safe_vars = 0;
 
 
  if (omega_solve_depth > 50)
  if (omega_solve_depth > 50)
    {
    {
      if (dump_file && (dump_flags & TDF_DETAILS))
      if (dump_file && (dump_flags & TDF_DETAILS))
        {
        {
          fprintf (dump_file,
          fprintf (dump_file,
                   "Solve depth = %d, in_approximate_mode = %d, aborting\n",
                   "Solve depth = %d, in_approximate_mode = %d, aborting\n",
                   omega_solve_depth, in_approximate_mode);
                   omega_solve_depth, in_approximate_mode);
          omega_print_problem (dump_file, pb);
          omega_print_problem (dump_file, pb);
        }
        }
      gcc_assert (0);
      gcc_assert (0);
    }
    }
 
 
  if (omega_solve_eq (pb, desired_res) == omega_false)
  if (omega_solve_eq (pb, desired_res) == omega_false)
    {
    {
      omega_solve_depth--;
      omega_solve_depth--;
      return omega_false;
      return omega_false;
    }
    }
 
 
  if (in_approximate_mode && !pb->num_geqs)
  if (in_approximate_mode && !pb->num_geqs)
    {
    {
      result = omega_true;
      result = omega_true;
      pb->num_vars = pb->safe_vars;
      pb->num_vars = pb->safe_vars;
      omega_problem_reduced (pb);
      omega_problem_reduced (pb);
    }
    }
  else
  else
    result = omega_solve_geq (pb, desired_res);
    result = omega_solve_geq (pb, desired_res);
 
 
  omega_solve_depth--;
  omega_solve_depth--;
 
 
  if (!omega_reduce_with_subs)
  if (!omega_reduce_with_subs)
    {
    {
      resurrect_subs (pb);
      resurrect_subs (pb);
      gcc_assert (please_no_equalities_in_simplified_problems
      gcc_assert (please_no_equalities_in_simplified_problems
                  || !result || pb->num_subs == 0);
                  || !result || pb->num_subs == 0);
    }
    }
 
 
  return result;
  return result;
}
}
 
 
/* Return true if red equations constrain the set of possible solutions.
/* Return true if red equations constrain the set of possible solutions.
   We assume that there are solutions to the black equations by
   We assume that there are solutions to the black equations by
   themselves, so if there is no solution to the combined problem, we
   themselves, so if there is no solution to the combined problem, we
   return true.  */
   return true.  */
 
 
bool
bool
omega_problem_has_red_equations (omega_pb pb)
omega_problem_has_red_equations (omega_pb pb)
{
{
  bool result;
  bool result;
  int e;
  int e;
  int i;
  int i;
 
 
  if (dump_file && (dump_flags & TDF_DETAILS))
  if (dump_file && (dump_flags & TDF_DETAILS))
    {
    {
      fprintf (dump_file, "Checking for red equations:\n");
      fprintf (dump_file, "Checking for red equations:\n");
      omega_print_problem (dump_file, pb);
      omega_print_problem (dump_file, pb);
    }
    }
 
 
  please_no_equalities_in_simplified_problems++;
  please_no_equalities_in_simplified_problems++;
  may_be_red++;
  may_be_red++;
 
 
  if (omega_single_result)
  if (omega_single_result)
    return_single_result++;
    return_single_result++;
 
 
  create_color = true;
  create_color = true;
  result = (omega_simplify_problem (pb) == omega_false);
  result = (omega_simplify_problem (pb) == omega_false);
 
 
  if (omega_single_result)
  if (omega_single_result)
    return_single_result--;
    return_single_result--;
 
 
  may_be_red--;
  may_be_red--;
  please_no_equalities_in_simplified_problems--;
  please_no_equalities_in_simplified_problems--;
 
 
  if (result)
  if (result)
    {
    {
      if (dump_file && (dump_flags & TDF_DETAILS))
      if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file, "Gist is FALSE\n");
        fprintf (dump_file, "Gist is FALSE\n");
 
 
      pb->num_subs = 0;
      pb->num_subs = 0;
      pb->num_geqs = 0;
      pb->num_geqs = 0;
      pb->num_eqs = 1;
      pb->num_eqs = 1;
      pb->eqs[0].color = omega_red;
      pb->eqs[0].color = omega_red;
 
 
      for (i = pb->num_vars; i > 0; i--)
      for (i = pb->num_vars; i > 0; i--)
        pb->eqs[0].coef[i] = 0;
        pb->eqs[0].coef[i] = 0;
 
 
      pb->eqs[0].coef[0] = 1;
      pb->eqs[0].coef[0] = 1;
      return true;
      return true;
    }
    }
 
 
  free_red_eliminations (pb);
  free_red_eliminations (pb);
  gcc_assert (pb->num_eqs == 0);
  gcc_assert (pb->num_eqs == 0);
 
 
  for (e = pb->num_geqs - 1; e >= 0; e--)
  for (e = pb->num_geqs - 1; e >= 0; e--)
    if (pb->geqs[e].color == omega_red)
    if (pb->geqs[e].color == omega_red)
      result = true;
      result = true;
 
 
  if (!result)
  if (!result)
    return false;
    return false;
 
 
  for (i = pb->safe_vars; i >= 1; i--)
  for (i = pb->safe_vars; i >= 1; i--)
    {
    {
      int ub = 0;
      int ub = 0;
      int lb = 0;
      int lb = 0;
 
 
      for (e = pb->num_geqs - 1; e >= 0; e--)
      for (e = pb->num_geqs - 1; e >= 0; e--)
        {
        {
          if (pb->geqs[e].coef[i])
          if (pb->geqs[e].coef[i])
            {
            {
              if (pb->geqs[e].coef[i] > 0)
              if (pb->geqs[e].coef[i] > 0)
                lb |= (1 + (pb->geqs[e].color == omega_red ? 1 : 0));
                lb |= (1 + (pb->geqs[e].color == omega_red ? 1 : 0));
 
 
              else
              else
                ub |= (1 + (pb->geqs[e].color == omega_red ? 1 : 0));
                ub |= (1 + (pb->geqs[e].color == omega_red ? 1 : 0));
            }
            }
        }
        }
 
 
      if (ub == 2 || lb == 2)
      if (ub == 2 || lb == 2)
        {
        {
 
 
          if (dump_file && (dump_flags & TDF_DETAILS))
          if (dump_file && (dump_flags & TDF_DETAILS))
            fprintf (dump_file, "checks for upper/lower bounds worked!\n");
            fprintf (dump_file, "checks for upper/lower bounds worked!\n");
 
 
          if (!omega_reduce_with_subs)
          if (!omega_reduce_with_subs)
            {
            {
              resurrect_subs (pb);
              resurrect_subs (pb);
              gcc_assert (pb->num_subs == 0);
              gcc_assert (pb->num_subs == 0);
            }
            }
 
 
          return true;
          return true;
        }
        }
    }
    }
 
 
 
 
  if (dump_file && (dump_flags & TDF_DETAILS))
  if (dump_file && (dump_flags & TDF_DETAILS))
    fprintf (dump_file,
    fprintf (dump_file,
             "*** Doing potentially expensive elimination tests "
             "*** Doing potentially expensive elimination tests "
             "for red equations\n");
             "for red equations\n");
 
 
  please_no_equalities_in_simplified_problems++;
  please_no_equalities_in_simplified_problems++;
  omega_eliminate_red (pb, true);
  omega_eliminate_red (pb, true);
  please_no_equalities_in_simplified_problems--;
  please_no_equalities_in_simplified_problems--;
 
 
  result = false;
  result = false;
  gcc_assert (pb->num_eqs == 0);
  gcc_assert (pb->num_eqs == 0);
 
 
  for (e = pb->num_geqs - 1; e >= 0; e--)
  for (e = pb->num_geqs - 1; e >= 0; e--)
    if (pb->geqs[e].color == omega_red)
    if (pb->geqs[e].color == omega_red)
      result = true;
      result = true;
 
 
  if (dump_file && (dump_flags & TDF_DETAILS))
  if (dump_file && (dump_flags & TDF_DETAILS))
    {
    {
      if (!result)
      if (!result)
        fprintf (dump_file,
        fprintf (dump_file,
                 "******************** Redundant Red Equations eliminated!!\n");
                 "******************** Redundant Red Equations eliminated!!\n");
      else
      else
        fprintf (dump_file,
        fprintf (dump_file,
                 "******************** Red Equations remain\n");
                 "******************** Red Equations remain\n");
 
 
      omega_print_problem (dump_file, pb);
      omega_print_problem (dump_file, pb);
    }
    }
 
 
  if (!omega_reduce_with_subs)
  if (!omega_reduce_with_subs)
    {
    {
      normalize_return_type r;
      normalize_return_type r;
 
 
      resurrect_subs (pb);
      resurrect_subs (pb);
      r = normalize_omega_problem (pb);
      r = normalize_omega_problem (pb);
      gcc_assert (r != normalize_false);
      gcc_assert (r != normalize_false);
 
 
      coalesce (pb);
      coalesce (pb);
      cleanout_wildcards (pb);
      cleanout_wildcards (pb);
      gcc_assert (pb->num_subs == 0);
      gcc_assert (pb->num_subs == 0);
    }
    }
 
 
  return result;
  return result;
}
}
 
 
/* Calls omega_simplify_problem in approximate mode.  */
/* Calls omega_simplify_problem in approximate mode.  */
 
 
enum omega_result
enum omega_result
omega_simplify_approximate (omega_pb pb)
omega_simplify_approximate (omega_pb pb)
{
{
  enum omega_result result;
  enum omega_result result;
 
 
  if (dump_file && (dump_flags & TDF_DETAILS))
  if (dump_file && (dump_flags & TDF_DETAILS))
    fprintf (dump_file, "(Entering approximate mode\n");
    fprintf (dump_file, "(Entering approximate mode\n");
 
 
  in_approximate_mode = true;
  in_approximate_mode = true;
  result = omega_simplify_problem (pb);
  result = omega_simplify_problem (pb);
  in_approximate_mode = false;
  in_approximate_mode = false;
 
 
  gcc_assert (pb->num_vars == pb->safe_vars);
  gcc_assert (pb->num_vars == pb->safe_vars);
  if (!omega_reduce_with_subs)
  if (!omega_reduce_with_subs)
    gcc_assert (pb->num_subs == 0);
    gcc_assert (pb->num_subs == 0);
 
 
  if (dump_file && (dump_flags & TDF_DETAILS))
  if (dump_file && (dump_flags & TDF_DETAILS))
    fprintf (dump_file, "Leaving approximate mode)\n");
    fprintf (dump_file, "Leaving approximate mode)\n");
 
 
  return result;
  return result;
}
}
 
 
 
 
/* Simplifies problem PB by eliminating redundant constraints and
/* Simplifies problem PB by eliminating redundant constraints and
   reducing the constraints system to a minimal form.  Returns
   reducing the constraints system to a minimal form.  Returns
   omega_true when the problem was successfully reduced, omega_unknown
   omega_true when the problem was successfully reduced, omega_unknown
   when the solver is unable to determine an answer.  */
   when the solver is unable to determine an answer.  */
 
 
enum omega_result
enum omega_result
omega_simplify_problem (omega_pb pb)
omega_simplify_problem (omega_pb pb)
{
{
  int i;
  int i;
 
 
  omega_found_reduction = omega_false;
  omega_found_reduction = omega_false;
 
 
  if (!pb->variables_initialized)
  if (!pb->variables_initialized)
    omega_initialize_variables (pb);
    omega_initialize_variables (pb);
 
 
  if (next_key * 3 > MAX_KEYS)
  if (next_key * 3 > MAX_KEYS)
    {
    {
      int e;
      int e;
 
 
      hash_version++;
      hash_version++;
      next_key = OMEGA_MAX_VARS + 1;
      next_key = OMEGA_MAX_VARS + 1;
 
 
      for (e = pb->num_geqs - 1; e >= 0; e--)
      for (e = pb->num_geqs - 1; e >= 0; e--)
        pb->geqs[e].touched = 1;
        pb->geqs[e].touched = 1;
 
 
      for (i = 0; i < HASH_TABLE_SIZE; i++)
      for (i = 0; i < HASH_TABLE_SIZE; i++)
        hash_master[i].touched = -1;
        hash_master[i].touched = -1;
 
 
      pb->hash_version = hash_version;
      pb->hash_version = hash_version;
    }
    }
 
 
  else if (pb->hash_version != hash_version)
  else if (pb->hash_version != hash_version)
    {
    {
      int e;
      int e;
 
 
      for (e = pb->num_geqs - 1; e >= 0; e--)
      for (e = pb->num_geqs - 1; e >= 0; e--)
        pb->geqs[e].touched = 1;
        pb->geqs[e].touched = 1;
 
 
      pb->hash_version = hash_version;
      pb->hash_version = hash_version;
    }
    }
 
 
  if (pb->num_vars > pb->num_eqs + 3 * pb->safe_vars)
  if (pb->num_vars > pb->num_eqs + 3 * pb->safe_vars)
    omega_free_eliminations (pb, pb->safe_vars);
    omega_free_eliminations (pb, pb->safe_vars);
 
 
  if (!may_be_red && pb->num_subs == 0 && pb->safe_vars == 0)
  if (!may_be_red && pb->num_subs == 0 && pb->safe_vars == 0)
    {
    {
      omega_found_reduction = omega_solve_problem (pb, omega_unknown);
      omega_found_reduction = omega_solve_problem (pb, omega_unknown);
 
 
      if (omega_found_reduction != omega_false
      if (omega_found_reduction != omega_false
          && !return_single_result)
          && !return_single_result)
        {
        {
          pb->num_geqs = 0;
          pb->num_geqs = 0;
          pb->num_eqs = 0;
          pb->num_eqs = 0;
          (*omega_when_reduced) (pb);
          (*omega_when_reduced) (pb);
        }
        }
 
 
      return omega_found_reduction;
      return omega_found_reduction;
    }
    }
 
 
  omega_solve_problem (pb, omega_simplify);
  omega_solve_problem (pb, omega_simplify);
 
 
  if (omega_found_reduction != omega_false)
  if (omega_found_reduction != omega_false)
    {
    {
      for (i = 1; omega_safe_var_p (pb, i); i++)
      for (i = 1; omega_safe_var_p (pb, i); i++)
        pb->forwarding_address[pb->var[i]] = i;
        pb->forwarding_address[pb->var[i]] = i;
 
 
      for (i = 0; i < pb->num_subs; i++)
      for (i = 0; i < pb->num_subs; i++)
        pb->forwarding_address[pb->subs[i].key] = -i - 1;
        pb->forwarding_address[pb->subs[i].key] = -i - 1;
    }
    }
 
 
  if (!omega_reduce_with_subs)
  if (!omega_reduce_with_subs)
    gcc_assert (please_no_equalities_in_simplified_problems
    gcc_assert (please_no_equalities_in_simplified_problems
                || omega_found_reduction == omega_false
                || omega_found_reduction == omega_false
                || pb->num_subs == 0);
                || pb->num_subs == 0);
 
 
  return omega_found_reduction;
  return omega_found_reduction;
}
}
 
 
/* Make variable VAR unprotected: it then can be eliminated.  */
/* Make variable VAR unprotected: it then can be eliminated.  */
 
 
void
void
omega_unprotect_variable (omega_pb pb, int var)
omega_unprotect_variable (omega_pb pb, int var)
{
{
  int e, idx;
  int e, idx;
  idx = pb->forwarding_address[var];
  idx = pb->forwarding_address[var];
 
 
  if (idx < 0)
  if (idx < 0)
    {
    {
      idx = -1 - idx;
      idx = -1 - idx;
      pb->num_subs--;
      pb->num_subs--;
 
 
      if (idx < pb->num_subs)
      if (idx < pb->num_subs)
        {
        {
          omega_copy_eqn (&pb->subs[idx], &pb->subs[pb->num_subs],
          omega_copy_eqn (&pb->subs[idx], &pb->subs[pb->num_subs],
                          pb->num_vars);
                          pb->num_vars);
          pb->forwarding_address[pb->subs[idx].key] = -idx - 1;
          pb->forwarding_address[pb->subs[idx].key] = -idx - 1;
        }
        }
    }
    }
  else
  else
    {
    {
      int *bring_to_life = XNEWVEC (int, OMEGA_MAX_VARS);
      int *bring_to_life = XNEWVEC (int, OMEGA_MAX_VARS);
      int e2;
      int e2;
 
 
      for (e = pb->num_subs - 1; e >= 0; e--)
      for (e = pb->num_subs - 1; e >= 0; e--)
        bring_to_life[e] = (pb->subs[e].coef[idx] != 0);
        bring_to_life[e] = (pb->subs[e].coef[idx] != 0);
 
 
      for (e2 = pb->num_subs - 1; e2 >= 0; e2--)
      for (e2 = pb->num_subs - 1; e2 >= 0; e2--)
        if (bring_to_life[e2])
        if (bring_to_life[e2])
          {
          {
            pb->num_vars++;
            pb->num_vars++;
            pb->safe_vars++;
            pb->safe_vars++;
 
 
            if (pb->safe_vars < pb->num_vars)
            if (pb->safe_vars < pb->num_vars)
              {
              {
                for (e = pb->num_geqs - 1; e >= 0; e--)
                for (e = pb->num_geqs - 1; e >= 0; e--)
                  {
                  {
                    pb->geqs[e].coef[pb->num_vars] =
                    pb->geqs[e].coef[pb->num_vars] =
                      pb->geqs[e].coef[pb->safe_vars];
                      pb->geqs[e].coef[pb->safe_vars];
 
 
                    pb->geqs[e].coef[pb->safe_vars] = 0;
                    pb->geqs[e].coef[pb->safe_vars] = 0;
                  }
                  }
 
 
                for (e = pb->num_eqs - 1; e >= 0; e--)
                for (e = pb->num_eqs - 1; e >= 0; e--)
                  {
                  {
                    pb->eqs[e].coef[pb->num_vars] =
                    pb->eqs[e].coef[pb->num_vars] =
                      pb->eqs[e].coef[pb->safe_vars];
                      pb->eqs[e].coef[pb->safe_vars];
 
 
                    pb->eqs[e].coef[pb->safe_vars] = 0;
                    pb->eqs[e].coef[pb->safe_vars] = 0;
                  }
                  }
 
 
                for (e = pb->num_subs - 1; e >= 0; e--)
                for (e = pb->num_subs - 1; e >= 0; e--)
                  {
                  {
                    pb->subs[e].coef[pb->num_vars] =
                    pb->subs[e].coef[pb->num_vars] =
                      pb->subs[e].coef[pb->safe_vars];
                      pb->subs[e].coef[pb->safe_vars];
 
 
                    pb->subs[e].coef[pb->safe_vars] = 0;
                    pb->subs[e].coef[pb->safe_vars] = 0;
                  }
                  }
 
 
                pb->var[pb->num_vars] = pb->var[pb->safe_vars];
                pb->var[pb->num_vars] = pb->var[pb->safe_vars];
                pb->forwarding_address[pb->var[pb->num_vars]] =
                pb->forwarding_address[pb->var[pb->num_vars]] =
                  pb->num_vars;
                  pb->num_vars;
              }
              }
            else
            else
              {
              {
                for (e = pb->num_geqs - 1; e >= 0; e--)
                for (e = pb->num_geqs - 1; e >= 0; e--)
                  pb->geqs[e].coef[pb->safe_vars] = 0;
                  pb->geqs[e].coef[pb->safe_vars] = 0;
 
 
                for (e = pb->num_eqs - 1; e >= 0; e--)
                for (e = pb->num_eqs - 1; e >= 0; e--)
                  pb->eqs[e].coef[pb->safe_vars] = 0;
                  pb->eqs[e].coef[pb->safe_vars] = 0;
 
 
                for (e = pb->num_subs - 1; e >= 0; e--)
                for (e = pb->num_subs - 1; e >= 0; e--)
                  pb->subs[e].coef[pb->safe_vars] = 0;
                  pb->subs[e].coef[pb->safe_vars] = 0;
              }
              }
 
 
            pb->var[pb->safe_vars] = pb->subs[e2].key;
            pb->var[pb->safe_vars] = pb->subs[e2].key;
            pb->forwarding_address[pb->subs[e2].key] = pb->safe_vars;
            pb->forwarding_address[pb->subs[e2].key] = pb->safe_vars;
 
 
            omega_copy_eqn (&(pb->eqs[pb->num_eqs]), &(pb->subs[e2]),
            omega_copy_eqn (&(pb->eqs[pb->num_eqs]), &(pb->subs[e2]),
                            pb->num_vars);
                            pb->num_vars);
            pb->eqs[pb->num_eqs++].coef[pb->safe_vars] = -1;
            pb->eqs[pb->num_eqs++].coef[pb->safe_vars] = -1;
            gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
            gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
 
 
            if (e2 < pb->num_subs - 1)
            if (e2 < pb->num_subs - 1)
              omega_copy_eqn (&(pb->subs[e2]), &(pb->subs[pb->num_subs - 1]),
              omega_copy_eqn (&(pb->subs[e2]), &(pb->subs[pb->num_subs - 1]),
                              pb->num_vars);
                              pb->num_vars);
 
 
            pb->num_subs--;
            pb->num_subs--;
          }
          }
 
 
      omega_unprotect_1 (pb, &idx, NULL);
      omega_unprotect_1 (pb, &idx, NULL);
      free (bring_to_life);
      free (bring_to_life);
    }
    }
 
 
  chain_unprotect (pb);
  chain_unprotect (pb);
}
}
 
 
/* Unprotects VAR and simplifies PB.  */
/* Unprotects VAR and simplifies PB.  */
 
 
enum omega_result
enum omega_result
omega_constrain_variable_sign (omega_pb pb, enum omega_eqn_color color,
omega_constrain_variable_sign (omega_pb pb, enum omega_eqn_color color,
                               int var, int sign)
                               int var, int sign)
{
{
  int n_vars = pb->num_vars;
  int n_vars = pb->num_vars;
  int e, j;
  int e, j;
  int k = pb->forwarding_address[var];
  int k = pb->forwarding_address[var];
 
 
  if (k < 0)
  if (k < 0)
    {
    {
      k = -1 - k;
      k = -1 - k;
 
 
      if (sign != 0)
      if (sign != 0)
        {
        {
          e = pb->num_geqs++;
          e = pb->num_geqs++;
          omega_copy_eqn (&pb->geqs[e], &pb->subs[k], pb->num_vars);
          omega_copy_eqn (&pb->geqs[e], &pb->subs[k], pb->num_vars);
 
 
          for (j = 0; j <= n_vars; j++)
          for (j = 0; j <= n_vars; j++)
            pb->geqs[e].coef[j] *= sign;
            pb->geqs[e].coef[j] *= sign;
 
 
          pb->geqs[e].coef[0]--;
          pb->geqs[e].coef[0]--;
          pb->geqs[e].touched = 1;
          pb->geqs[e].touched = 1;
          pb->geqs[e].color = color;
          pb->geqs[e].color = color;
        }
        }
      else
      else
        {
        {
          e = pb->num_eqs++;
          e = pb->num_eqs++;
          gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
          gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
          omega_copy_eqn (&pb->eqs[e], &pb->subs[k], pb->num_vars);
          omega_copy_eqn (&pb->eqs[e], &pb->subs[k], pb->num_vars);
          pb->eqs[e].color = color;
          pb->eqs[e].color = color;
        }
        }
    }
    }
  else if (sign != 0)
  else if (sign != 0)
    {
    {
      e = pb->num_geqs++;
      e = pb->num_geqs++;
      omega_init_eqn_zero (&pb->geqs[e], pb->num_vars);
      omega_init_eqn_zero (&pb->geqs[e], pb->num_vars);
      pb->geqs[e].coef[k] = sign;
      pb->geqs[e].coef[k] = sign;
      pb->geqs[e].coef[0] = -1;
      pb->geqs[e].coef[0] = -1;
      pb->geqs[e].touched = 1;
      pb->geqs[e].touched = 1;
      pb->geqs[e].color = color;
      pb->geqs[e].color = color;
    }
    }
  else
  else
    {
    {
      e = pb->num_eqs++;
      e = pb->num_eqs++;
      gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
      gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
      omega_init_eqn_zero (&pb->eqs[e], pb->num_vars);
      omega_init_eqn_zero (&pb->eqs[e], pb->num_vars);
      pb->eqs[e].coef[k] = 1;
      pb->eqs[e].coef[k] = 1;
      pb->eqs[e].color = color;
      pb->eqs[e].color = color;
    }
    }
 
 
  omega_unprotect_variable (pb, var);
  omega_unprotect_variable (pb, var);
  return omega_simplify_problem (pb);
  return omega_simplify_problem (pb);
}
}
 
 
/* Add an equation "VAR = VALUE" with COLOR to PB.  */
/* Add an equation "VAR = VALUE" with COLOR to PB.  */
 
 
void
void
omega_constrain_variable_value (omega_pb pb, enum omega_eqn_color color,
omega_constrain_variable_value (omega_pb pb, enum omega_eqn_color color,
                                int var, int value)
                                int var, int value)
{
{
  int e;
  int e;
  int k = pb->forwarding_address[var];
  int k = pb->forwarding_address[var];
 
 
  if (k < 0)
  if (k < 0)
    {
    {
      k = -1 - k;
      k = -1 - k;
      e = pb->num_eqs++;
      e = pb->num_eqs++;
      gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
      gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
      omega_copy_eqn (&pb->eqs[e], &pb->subs[k], pb->num_vars);
      omega_copy_eqn (&pb->eqs[e], &pb->subs[k], pb->num_vars);
      pb->eqs[e].coef[0] -= value;
      pb->eqs[e].coef[0] -= value;
    }
    }
  else
  else
    {
    {
      e = pb->num_eqs++;
      e = pb->num_eqs++;
      omega_init_eqn_zero (&pb->eqs[e], pb->num_vars);
      omega_init_eqn_zero (&pb->eqs[e], pb->num_vars);
      pb->eqs[e].coef[k] = 1;
      pb->eqs[e].coef[k] = 1;
      pb->eqs[e].coef[0] = -value;
      pb->eqs[e].coef[0] = -value;
    }
    }
 
 
  pb->eqs[e].color = color;
  pb->eqs[e].color = color;
}
}
 
 
/* Return false when the upper and lower bounds are not coupled.
/* Return false when the upper and lower bounds are not coupled.
   Initialize the bounds LOWER_BOUND and UPPER_BOUND for the values of
   Initialize the bounds LOWER_BOUND and UPPER_BOUND for the values of
   variable I.  */
   variable I.  */
 
 
bool
bool
omega_query_variable (omega_pb pb, int i, int *lower_bound, int *upper_bound)
omega_query_variable (omega_pb pb, int i, int *lower_bound, int *upper_bound)
{
{
  int n_vars = pb->num_vars;
  int n_vars = pb->num_vars;
  int e, j;
  int e, j;
  bool is_simple;
  bool is_simple;
  bool coupled = false;
  bool coupled = false;
 
 
  *lower_bound = neg_infinity;
  *lower_bound = neg_infinity;
  *upper_bound = pos_infinity;
  *upper_bound = pos_infinity;
  i = pb->forwarding_address[i];
  i = pb->forwarding_address[i];
 
 
  if (i < 0)
  if (i < 0)
    {
    {
      i = -i - 1;
      i = -i - 1;
 
 
      for (j = 1; j <= n_vars; j++)
      for (j = 1; j <= n_vars; j++)
        if (pb->subs[i].coef[j] != 0)
        if (pb->subs[i].coef[j] != 0)
          return true;
          return true;
 
 
      *upper_bound = *lower_bound = pb->subs[i].coef[0];
      *upper_bound = *lower_bound = pb->subs[i].coef[0];
      return false;
      return false;
    }
    }
 
 
  for (e = pb->num_subs - 1; e >= 0; e--)
  for (e = pb->num_subs - 1; e >= 0; e--)
    if (pb->subs[e].coef[i] != 0)
    if (pb->subs[e].coef[i] != 0)
      coupled = true;
      coupled = true;
 
 
  for (e = pb->num_eqs - 1; e >= 0; e--)
  for (e = pb->num_eqs - 1; e >= 0; e--)
    if (pb->eqs[e].coef[i] != 0)
    if (pb->eqs[e].coef[i] != 0)
      {
      {
        is_simple = true;
        is_simple = true;
 
 
        for (j = 1; j <= n_vars; j++)
        for (j = 1; j <= n_vars; j++)
          if (i != j && pb->eqs[e].coef[j] != 0)
          if (i != j && pb->eqs[e].coef[j] != 0)
            {
            {
              is_simple = false;
              is_simple = false;
              coupled = true;
              coupled = true;
              break;
              break;
            }
            }
 
 
        if (!is_simple)
        if (!is_simple)
          continue;
          continue;
        else
        else
          {
          {
            *lower_bound = *upper_bound =
            *lower_bound = *upper_bound =
              -pb->eqs[e].coef[i] * pb->eqs[e].coef[0];
              -pb->eqs[e].coef[i] * pb->eqs[e].coef[0];
            return false;
            return false;
          }
          }
      }
      }
 
 
  for (e = pb->num_geqs - 1; e >= 0; e--)
  for (e = pb->num_geqs - 1; e >= 0; e--)
    if (pb->geqs[e].coef[i] != 0)
    if (pb->geqs[e].coef[i] != 0)
      {
      {
        if (pb->geqs[e].key == i)
        if (pb->geqs[e].key == i)
          *lower_bound = MAX (*lower_bound, -pb->geqs[e].coef[0]);
          *lower_bound = MAX (*lower_bound, -pb->geqs[e].coef[0]);
 
 
        else if (pb->geqs[e].key == -i)
        else if (pb->geqs[e].key == -i)
          *upper_bound = MIN (*upper_bound, pb->geqs[e].coef[0]);
          *upper_bound = MIN (*upper_bound, pb->geqs[e].coef[0]);
 
 
        else
        else
          coupled = true;
          coupled = true;
      }
      }
 
 
  return coupled;
  return coupled;
}
}
 
 
/* Sets the lower bound L and upper bound U for the values of variable
/* Sets the lower bound L and upper bound U for the values of variable
   I, and sets COULD_BE_ZERO to true if variable I might take value
   I, and sets COULD_BE_ZERO to true if variable I might take value
   zero.  LOWER_BOUND and UPPER_BOUND are bounds on the values of
   zero.  LOWER_BOUND and UPPER_BOUND are bounds on the values of
   variable I.  */
   variable I.  */
 
 
static void
static void
query_coupled_variable (omega_pb pb, int i, int *l, int *u,
query_coupled_variable (omega_pb pb, int i, int *l, int *u,
                        bool *could_be_zero, int lower_bound, int upper_bound)
                        bool *could_be_zero, int lower_bound, int upper_bound)
{
{
  int e, b1, b2;
  int e, b1, b2;
  eqn eqn;
  eqn eqn;
  int sign;
  int sign;
  int v;
  int v;
 
 
  /* Preconditions.  */
  /* Preconditions.  */
  gcc_assert (abs (pb->forwarding_address[i]) == 1
  gcc_assert (abs (pb->forwarding_address[i]) == 1
              && pb->num_vars + pb->num_subs == 2
              && pb->num_vars + pb->num_subs == 2
              && pb->num_eqs + pb->num_subs == 1);
              && pb->num_eqs + pb->num_subs == 1);
 
 
  /* Define variable I in terms of variable V.  */
  /* Define variable I in terms of variable V.  */
  if (pb->forwarding_address[i] == -1)
  if (pb->forwarding_address[i] == -1)
    {
    {
      eqn = &pb->subs[0];
      eqn = &pb->subs[0];
      sign = 1;
      sign = 1;
      v = 1;
      v = 1;
    }
    }
  else
  else
    {
    {
      eqn = &pb->eqs[0];
      eqn = &pb->eqs[0];
      sign = -eqn->coef[1];
      sign = -eqn->coef[1];
      v = 2;
      v = 2;
    }
    }
 
 
  for (e = pb->num_geqs - 1; e >= 0; e--)
  for (e = pb->num_geqs - 1; e >= 0; e--)
    if (pb->geqs[e].coef[v] != 0)
    if (pb->geqs[e].coef[v] != 0)
      {
      {
        if (pb->geqs[e].coef[v] == 1)
        if (pb->geqs[e].coef[v] == 1)
          lower_bound = MAX (lower_bound, -pb->geqs[e].coef[0]);
          lower_bound = MAX (lower_bound, -pb->geqs[e].coef[0]);
 
 
        else
        else
          upper_bound = MIN (upper_bound, pb->geqs[e].coef[0]);
          upper_bound = MIN (upper_bound, pb->geqs[e].coef[0]);
      }
      }
 
 
  if (lower_bound > upper_bound)
  if (lower_bound > upper_bound)
    {
    {
      *l = pos_infinity;
      *l = pos_infinity;
      *u = neg_infinity;
      *u = neg_infinity;
      *could_be_zero = 0;
      *could_be_zero = 0;
      return;
      return;
    }
    }
 
 
  if (lower_bound == neg_infinity)
  if (lower_bound == neg_infinity)
    {
    {
      if (eqn->coef[v] > 0)
      if (eqn->coef[v] > 0)
        b1 = sign * neg_infinity;
        b1 = sign * neg_infinity;
 
 
      else
      else
        b1 = -sign * neg_infinity;
        b1 = -sign * neg_infinity;
    }
    }
  else
  else
    b1 = sign * (eqn->coef[0] + eqn->coef[v] * lower_bound);
    b1 = sign * (eqn->coef[0] + eqn->coef[v] * lower_bound);
 
 
  if (upper_bound == pos_infinity)
  if (upper_bound == pos_infinity)
    {
    {
      if (eqn->coef[v] > 0)
      if (eqn->coef[v] > 0)
        b2 = sign * pos_infinity;
        b2 = sign * pos_infinity;
 
 
      else
      else
        b2 = -sign * pos_infinity;
        b2 = -sign * pos_infinity;
    }
    }
  else
  else
    b2 = sign * (eqn->coef[0] + eqn->coef[v] * upper_bound);
    b2 = sign * (eqn->coef[0] + eqn->coef[v] * upper_bound);
 
 
  *l = MAX (*l, b1 <= b2 ? b1 : b2);
  *l = MAX (*l, b1 <= b2 ? b1 : b2);
  *u = MIN (*u, b1 <= b2 ? b2 : b1);
  *u = MIN (*u, b1 <= b2 ? b2 : b1);
 
 
  *could_be_zero = (*l <= 0 && 0 <= *u
  *could_be_zero = (*l <= 0 && 0 <= *u
                    && int_mod (eqn->coef[0], abs (eqn->coef[v])) == 0);
                    && int_mod (eqn->coef[0], abs (eqn->coef[v])) == 0);
}
}
 
 
/* Return false when a lower bound L and an upper bound U for variable
/* Return false when a lower bound L and an upper bound U for variable
   I in problem PB have been initialized.  */
   I in problem PB have been initialized.  */
 
 
bool
bool
omega_query_variable_bounds (omega_pb pb, int i, int *l, int *u)
omega_query_variable_bounds (omega_pb pb, int i, int *l, int *u)
{
{
  *l = neg_infinity;
  *l = neg_infinity;
  *u = pos_infinity;
  *u = pos_infinity;
 
 
  if (!omega_query_variable (pb, i, l, u)
  if (!omega_query_variable (pb, i, l, u)
      || (pb->num_vars == 1 && pb->forwarding_address[i] == 1))
      || (pb->num_vars == 1 && pb->forwarding_address[i] == 1))
    return false;
    return false;
 
 
  if (abs (pb->forwarding_address[i]) == 1
  if (abs (pb->forwarding_address[i]) == 1
      && pb->num_vars + pb->num_subs == 2
      && pb->num_vars + pb->num_subs == 2
      && pb->num_eqs + pb->num_subs == 1)
      && pb->num_eqs + pb->num_subs == 1)
    {
    {
      bool could_be_zero;
      bool could_be_zero;
      query_coupled_variable (pb, i, l, u, &could_be_zero, neg_infinity,
      query_coupled_variable (pb, i, l, u, &could_be_zero, neg_infinity,
                              pos_infinity);
                              pos_infinity);
      return false;
      return false;
    }
    }
 
 
  return true;
  return true;
}
}
 
 
/* For problem PB, return an integer that represents the classic data
/* For problem PB, return an integer that represents the classic data
   dependence direction in function of the DD_LT, DD_EQ and DD_GT bit
   dependence direction in function of the DD_LT, DD_EQ and DD_GT bit
   masks that are added to the result.  When DIST_KNOWN is true, DIST
   masks that are added to the result.  When DIST_KNOWN is true, DIST
   is set to the classic data dependence distance.  LOWER_BOUND and
   is set to the classic data dependence distance.  LOWER_BOUND and
   UPPER_BOUND are bounds on the value of variable I, for example, it
   UPPER_BOUND are bounds on the value of variable I, for example, it
   is possible to narrow the iteration domain with safe approximations
   is possible to narrow the iteration domain with safe approximations
   of loop counts, and thus discard some data dependences that cannot
   of loop counts, and thus discard some data dependences that cannot
   occur.  */
   occur.  */
 
 
int
int
omega_query_variable_signs (omega_pb pb, int i, int dd_lt,
omega_query_variable_signs (omega_pb pb, int i, int dd_lt,
                            int dd_eq, int dd_gt, int lower_bound,
                            int dd_eq, int dd_gt, int lower_bound,
                            int upper_bound, bool *dist_known, int *dist)
                            int upper_bound, bool *dist_known, int *dist)
{
{
  int result;
  int result;
  int l, u;
  int l, u;
  bool could_be_zero;
  bool could_be_zero;
 
 
  l = neg_infinity;
  l = neg_infinity;
  u = pos_infinity;
  u = pos_infinity;
 
 
  omega_query_variable (pb, i, &l, &u);
  omega_query_variable (pb, i, &l, &u);
  query_coupled_variable (pb, i, &l, &u, &could_be_zero, lower_bound,
  query_coupled_variable (pb, i, &l, &u, &could_be_zero, lower_bound,
                          upper_bound);
                          upper_bound);
  result = 0;
  result = 0;
 
 
  if (l < 0)
  if (l < 0)
    result |= dd_gt;
    result |= dd_gt;
 
 
  if (u > 0)
  if (u > 0)
    result |= dd_lt;
    result |= dd_lt;
 
 
  if (could_be_zero)
  if (could_be_zero)
    result |= dd_eq;
    result |= dd_eq;
 
 
  if (l == u)
  if (l == u)
    {
    {
      *dist_known = true;
      *dist_known = true;
      *dist = l;
      *dist = l;
    }
    }
  else
  else
    *dist_known = false;
    *dist_known = false;
 
 
  return result;
  return result;
}
}
 
 
/* Initialize PB as an Omega problem with NVARS variables and NPROT
/* Initialize PB as an Omega problem with NVARS variables and NPROT
   safe variables.  Safe variables are not eliminated during the
   safe variables.  Safe variables are not eliminated during the
   Fourier-Motzkin elimination.  Safe variables are all those
   Fourier-Motzkin elimination.  Safe variables are all those
   variables that are placed at the beginning of the array of
   variables that are placed at the beginning of the array of
   variables: P->var[0, ..., NPROT - 1].  */
   variables: P->var[0, ..., NPROT - 1].  */
 
 
omega_pb
omega_pb
omega_alloc_problem (int nvars, int nprot)
omega_alloc_problem (int nvars, int nprot)
{
{
  omega_pb pb;
  omega_pb pb;
 
 
  gcc_assert (nvars <= OMEGA_MAX_VARS);
  gcc_assert (nvars <= OMEGA_MAX_VARS);
  omega_initialize ();
  omega_initialize ();
 
 
  /* Allocate and initialize PB.  */
  /* Allocate and initialize PB.  */
  pb = XCNEW (struct omega_pb_d);
  pb = XCNEW (struct omega_pb_d);
  pb->var = XCNEWVEC (int, OMEGA_MAX_VARS + 2);
  pb->var = XCNEWVEC (int, OMEGA_MAX_VARS + 2);
  pb->forwarding_address = XCNEWVEC (int, OMEGA_MAX_VARS + 2);
  pb->forwarding_address = XCNEWVEC (int, OMEGA_MAX_VARS + 2);
  pb->geqs = omega_alloc_eqns (0, OMEGA_MAX_GEQS);
  pb->geqs = omega_alloc_eqns (0, OMEGA_MAX_GEQS);
  pb->eqs = omega_alloc_eqns (0, OMEGA_MAX_EQS);
  pb->eqs = omega_alloc_eqns (0, OMEGA_MAX_EQS);
  pb->subs = omega_alloc_eqns (0, OMEGA_MAX_VARS + 1);
  pb->subs = omega_alloc_eqns (0, OMEGA_MAX_VARS + 1);
 
 
  pb->hash_version = hash_version;
  pb->hash_version = hash_version;
  pb->num_vars = nvars;
  pb->num_vars = nvars;
  pb->safe_vars = nprot;
  pb->safe_vars = nprot;
  pb->variables_initialized = false;
  pb->variables_initialized = false;
  pb->variables_freed = false;
  pb->variables_freed = false;
  pb->num_eqs = 0;
  pb->num_eqs = 0;
  pb->num_geqs = 0;
  pb->num_geqs = 0;
  pb->num_subs = 0;
  pb->num_subs = 0;
  return pb;
  return pb;
}
}
 
 
/* Keeps the state of the initialization.  */
/* Keeps the state of the initialization.  */
static bool omega_initialized = false;
static bool omega_initialized = false;
 
 
/* Initialization of the Omega solver.  */
/* Initialization of the Omega solver.  */
 
 
void
void
omega_initialize (void)
omega_initialize (void)
{
{
  int i;
  int i;
 
 
  if (omega_initialized)
  if (omega_initialized)
    return;
    return;
 
 
  next_wild_card = 0;
  next_wild_card = 0;
  next_key = OMEGA_MAX_VARS + 1;
  next_key = OMEGA_MAX_VARS + 1;
  packing = XCNEWVEC (int, OMEGA_MAX_VARS);
  packing = XCNEWVEC (int, OMEGA_MAX_VARS);
  fast_lookup = XCNEWVEC (int, MAX_KEYS * 2);
  fast_lookup = XCNEWVEC (int, MAX_KEYS * 2);
  fast_lookup_red = XCNEWVEC (int, MAX_KEYS * 2);
  fast_lookup_red = XCNEWVEC (int, MAX_KEYS * 2);
  hash_master = omega_alloc_eqns (0, HASH_TABLE_SIZE);
  hash_master = omega_alloc_eqns (0, HASH_TABLE_SIZE);
 
 
  for (i = 0; i < HASH_TABLE_SIZE; i++)
  for (i = 0; i < HASH_TABLE_SIZE; i++)
    hash_master[i].touched = -1;
    hash_master[i].touched = -1;
 
 
  sprintf (wild_name[0], "1");
  sprintf (wild_name[0], "1");
  sprintf (wild_name[1], "a");
  sprintf (wild_name[1], "a");
  sprintf (wild_name[2], "b");
  sprintf (wild_name[2], "b");
  sprintf (wild_name[3], "c");
  sprintf (wild_name[3], "c");
  sprintf (wild_name[4], "d");
  sprintf (wild_name[4], "d");
  sprintf (wild_name[5], "e");
  sprintf (wild_name[5], "e");
  sprintf (wild_name[6], "f");
  sprintf (wild_name[6], "f");
  sprintf (wild_name[7], "g");
  sprintf (wild_name[7], "g");
  sprintf (wild_name[8], "h");
  sprintf (wild_name[8], "h");
  sprintf (wild_name[9], "i");
  sprintf (wild_name[9], "i");
  sprintf (wild_name[10], "j");
  sprintf (wild_name[10], "j");
  sprintf (wild_name[11], "k");
  sprintf (wild_name[11], "k");
  sprintf (wild_name[12], "l");
  sprintf (wild_name[12], "l");
  sprintf (wild_name[13], "m");
  sprintf (wild_name[13], "m");
  sprintf (wild_name[14], "n");
  sprintf (wild_name[14], "n");
  sprintf (wild_name[15], "o");
  sprintf (wild_name[15], "o");
  sprintf (wild_name[16], "p");
  sprintf (wild_name[16], "p");
  sprintf (wild_name[17], "q");
  sprintf (wild_name[17], "q");
  sprintf (wild_name[18], "r");
  sprintf (wild_name[18], "r");
  sprintf (wild_name[19], "s");
  sprintf (wild_name[19], "s");
  sprintf (wild_name[20], "t");
  sprintf (wild_name[20], "t");
  sprintf (wild_name[40 - 1], "alpha");
  sprintf (wild_name[40 - 1], "alpha");
  sprintf (wild_name[40 - 2], "beta");
  sprintf (wild_name[40 - 2], "beta");
  sprintf (wild_name[40 - 3], "gamma");
  sprintf (wild_name[40 - 3], "gamma");
  sprintf (wild_name[40 - 4], "delta");
  sprintf (wild_name[40 - 4], "delta");
  sprintf (wild_name[40 - 5], "tau");
  sprintf (wild_name[40 - 5], "tau");
  sprintf (wild_name[40 - 6], "sigma");
  sprintf (wild_name[40 - 6], "sigma");
  sprintf (wild_name[40 - 7], "chi");
  sprintf (wild_name[40 - 7], "chi");
  sprintf (wild_name[40 - 8], "omega");
  sprintf (wild_name[40 - 8], "omega");
  sprintf (wild_name[40 - 9], "pi");
  sprintf (wild_name[40 - 9], "pi");
  sprintf (wild_name[40 - 10], "ni");
  sprintf (wild_name[40 - 10], "ni");
  sprintf (wild_name[40 - 11], "Alpha");
  sprintf (wild_name[40 - 11], "Alpha");
  sprintf (wild_name[40 - 12], "Beta");
  sprintf (wild_name[40 - 12], "Beta");
  sprintf (wild_name[40 - 13], "Gamma");
  sprintf (wild_name[40 - 13], "Gamma");
  sprintf (wild_name[40 - 14], "Delta");
  sprintf (wild_name[40 - 14], "Delta");
  sprintf (wild_name[40 - 15], "Tau");
  sprintf (wild_name[40 - 15], "Tau");
  sprintf (wild_name[40 - 16], "Sigma");
  sprintf (wild_name[40 - 16], "Sigma");
  sprintf (wild_name[40 - 17], "Chi");
  sprintf (wild_name[40 - 17], "Chi");
  sprintf (wild_name[40 - 18], "Omega");
  sprintf (wild_name[40 - 18], "Omega");
  sprintf (wild_name[40 - 19], "xxx");
  sprintf (wild_name[40 - 19], "xxx");
 
 
  omega_initialized = true;
  omega_initialized = true;
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.