/* Vladimir Kotlyar  February 1996
 *
 *
 *
 * NOTE: To be consistent with descriptions of algorithms and
 *       the matrix library the indices start with 1
 */

#ifndef _a_ineq_private_h
#define _a_ineq_private_h

#include <limits.h>

#ifndef _a_range_h
#include "alpha_range.h"
#endif


/***********************************************************************
 *			     INEQUALITIES
 ***********************************************************************/

/**************************************************/

struct xa_ineq_term_s {
  int		varind;
  int		coeff;
};

typedef struct xa_ineq_term_s  xa_ineq_term_t;
typedef struct xa_ineq_term_s *xa_ineq_term;

#define	xa_varind_ineq_term(e)		((e)->varind)
#define	xa_coeff_ineq_term(e)		((e)->coeff)

/**************************************************/

struct xa_ineq_s {
  int			normalized : 1;
  short			nterm;
  int			const_term;
  int			tag;
  xa_ineq_term_t	*terms;
};

typedef struct xa_ineq_s  xa_ineq_t;
typedef struct xa_ineq_s *xa_ineq;

#define	xa_nterm_ineq(i)		((i)->nterm)
#define xa_const_ineq(i)		((i)->const_term)
#define xa_tag_ineq(i)			((i)->tag)
#define xa_terms_ineq(i)		((i)->terms)
#define xa_term_ineq(i,k)		((i)->terms + (xa_check_range((k),xa_nterm_ineq(i)+1),((k)-1)))
#define xa_varind_ineq(i,k)		(xa_varind_ineq_term(xa_term_ineq((i),(k))))
#define xa_coeff_ineq(i,k)		(xa_coeff_ineq_term(xa_term_ineq((i),(k))))
#define xa_maxvarind_ineq(i)		(xa_varind_ineq((i),xa_nterm_ineq(i)))
#define xa_set_normalized_ineq(i)	((i)->normalized = 1)
#define xa_reset_normalized_ineq(i)	((i)->normalized = 0)
#define xa_is_normalized_ineq(i)	((i)->normalized != 0)

#define xa_verify_sentinel_ineq(i)	(assert(INT_MAX == ((i)->terms[(i)->nterm].varind)))
#define xa_set_sentinel_ineq(i)		((i)->terms[(i)->nterm].varind = INT_MAX)

#define XA_FOR_TERMS_IN_INEQ(ineq,varind,coeff) \
{int varind; int coeff; int __for_terms_k; \
   for (__for_terms_k = 1; __for_terms_k <= xa_nterm_ineq(ineq); __for_terms_k++) {\
      varind = xa_varind_ineq(ineq,__for_terms_k); \
      coeff = xa_coeff_ineq(ineq,__for_terms_k); \
      assert (coeff != 0);

#define XA_END_TERMS_IN_INEQ \
   }}

xa_ineq xa_alloc_ineq (arena_info *arena, int nterms);
void 	xa_compute_tag_ineq (xa_ineq ineq);
void 	xa_verify_sorted (xa_ineq ineq);


/***********************************************************************
 *			LISTS OF INEQUALITIES
 ***********************************************************************/

typedef struct xa_ineq_list_elt_s	xa_ineq_list_elt_t;
typedef struct xa_ineq_list_elt_s	*xa_ineq_list_elt;


struct xa_ineq_list_elt_s {
  xa_ineq		ineq;
  xa_ineq_list_elt 	next;
  xa_ineq_list_elt 	prev;
};

#define xa_ineq_ineq_list_elt(elt)	((elt)->ineq)
#define xa_next_ineq_list_elt(elt)	((elt)->next)
#define xa_prev_ineq_list_elt(elt)	((elt)->prev)
#define xa_is_equal_ineq_list_elt(e1,e2)		((e1) == (e2))

struct xa_ineq_list_s {
  xa_ineq_list_elt	h;
  int			n;
};

typedef struct xa_ineq_list_s 		xa_ineq_list_t;
typedef struct xa_ineq_list_s 		*xa_ineq_list;

#define xa_head_ineq_list(l)		((l)->h)
#define xa_length_ineq_list(l)		((l)->n)

/*
 * a deletion of an element does not disrupt the FOR loop
 * Moreover, the loop is used to clean up the list
 */
#define XA_FOR_INEQ_IN_LIST(l,ineq,elt) \
{  xa_ineq_list_elt elt;\
   xa_ineq_list_elt __for_next; \
   xa_ineq ineq; \
   for (elt = xa_head_ineq_list(l); elt; elt = __for_next) {\
      __for_next = xa_next_ineq_list_elt(elt); \
      ineq = xa_ineq_ineq_list_elt(elt);


#define XA_END_INEQ_IN_LIST \
   }}


xa_ineq_list	xa_make_ineq_list (arena_info *arena);
void		xa_clear_ineq_list (xa_ineq_list l);
void		xa_add_ineq_list (arena_info *arena, xa_ineq_list l, xa_ineq ineq);
void		xa_delete_ineq_list_elt (xa_ineq_list l, xa_ineq_list_elt e);



#endif


