public class PointRelation extends Relation
{
	public static final short L = 1;
	public static final short E = 2;
	public static final short G = 4;
	public static final short EL = L | E;
	public static final short GE = G | E;
	public static final short LG = L | G;
	public static final short ANY = L | G | E;
	
	public PointRelation()
	{
	}
	
	public PointRelation(String s) throws FormatException
	{
		set(s);
	}
	
	public PointRelation(int d) throws FormatException
	{
		set(d);
	}
	
    public String toString()
    {
        // This depends on the allocation
        // of values to relations as shown:
        //     0  1  2  3  4  5  6  7
        //   | 0  <  =  =< >  <> >= *
    	final String strings[] = {"null", "<", "=", "=<", ">",
    		"<>", ">=", "*"};
        return strings[data];
    }

    public void set(String s) throws FormatException
    {
    	if (s.equals("<"))
    		data = L;
    	else if (s.equals("="))
    		data = E;
    	else if (s.equals(">"))
    		data = G;
    	else if (s.equals("=<"))
    		data = EL;
    	else if (s.equals(">="))
    		data = GE;
    	else if (s.equals("<>"))
    		data = LG;
    	else if (s.equals("*"))
    		data = ANY;
    	else if (s.equals("null"))
    		data = 0;
    	else
            throw (new FormatException
                ("Bad point relation string: " + s));
    }

	public void set(int d) throws FormatException
	{
		if (d <= ANY)
			data = (short)d;
		else
			throw (new FormatException
                ("Bad point relation number: " + d));
	}
	
	public void setRandom()
	{
		// NB depends on representation of relations
		data = (short)((Math.random() * ANY) + 1);
	}
	
	public void setRandomDeterminate()
	{
		// NB depends on representation of relations
		data = (short)(1 << (int)(Math.random() * 3));
	}
	
	public boolean isDeterminate()
	{
		return (data == L || data == E || data == G);
	}
	
	public boolean isAny()
	{
		return (data == ANY);
	}
	
    public Relation intersection(Relation r)
    {
        // This method is derived from class relation
        try
        {
        	return new PointRelation(dataIntersection(r));
        }
        catch (FormatException e)
        {
        	return new PointRelation();
        }
    }

    public Relation inverse()
    {
        // This method is derived from class relation
        try
        {
        	if (data == L)
        		return new PointRelation(G);
        	else if (data == G)
        		return new PointRelation(L);
        	else if (data == EL)
        		return new PointRelation(GE);
        	else if (data == GE)
        		return new PointRelation(EL);
        	else
        		return new PointRelation(data);
        }
        catch (FormatException e)
        {
        	return new PointRelation();
        }
    }

    public Relation transition(Relation r)
    {
        // This method is derived from class relation
        // to do: code goes here
        // This transition table depends on the allocation
        // of values to relations as shown:
        //     0  1  2  3  4  5  6  7
        //   | 0  <  =  =< >  <> >= *
        // --------------------------
        // 0 | 0  0  0  0  0  0  0  0
        // < | 0  <  <  <  *  *  *  *
        // = | 0  <  =  =< >  <> >= *
        // =<| 0  <  =< =< *  *  *  *
        // > | 0  *  >  *  >  *  >  *
        // <>| 0  *  <> *  *  *  *  *
        // >=| 0  *  >= *  >  *  >= *
        // * | 0  *  *  *  *  *  *  *
        final short transitionTable[][] =
        {	{0, 0, 0, 0, 0, 0, 0, 0},
        	{0, 1, 1, 1, 7, 7, 7, 7},
        	{0, 1, 2, 3, 4, 5, 6, 7},
        	{0, 1, 3, 3, 7, 7, 7, 7},
        	{0, 7, 4, 7, 4, 7, 4, 7},
        	{0, 7, 5, 7, 7, 7, 7, 7},
        	{0, 7, 6, 7, 4, 7, 6, 7},
        	{0, 7, 7, 7, 7, 7, 7, 7} };
        	
        try
        {
			return new PointRelation(transitionTable[data][r.data]);
        }
        catch (FormatException e)
        {
        	return new PointRelation();
        }
    }

    public Relation union(Relation r)
    {
        // This method is derived from class relation
        try
        {
        	return new PointRelation(dataUnion(r));
        }
        catch (FormatException e)
        {
        	return new PointRelation();
        }
    }
    
	public Relation propagate(Relation r2, Relation r3)
	{
		//Algorithm 20, function propagate(r1, r2, r3) [r1 = this]
		try
		{
			if (data == E) return r2.transition(r3); //1
			else if (r2.data == E) return transition(r3); //2
			else if (r3.data == E) return r2.transition(this); //3
			else if (data == L && r2.data == L && r3.data == L)
				return new PointRelation(L); //4
			else if (data == G && r2.data == G && r3.data == G)
				return new PointRelation(G); //4
			else return new PointRelation(ANY); //5
		}
		catch (FormatException e)
		{
			throw new RuntimeException("Unexpected FormatException "
				+ e.toString());
		}
	}
}