package com.googlecode.prolog_cafe.lang;

import com.googlecode.prolog_cafe.exceptions.EvaluationException;
import com.googlecode.prolog_cafe.exceptions.IllegalTypeException;

/**
 * Floating point number.
 * The class <code>DoubleTerm</code> wraps a value of 
 * primitive type <code>double</code>.
 *
 * <pre>
 * Term t = new DoubleTerm(3.3333);
 * double d = ((DoubleTerm)t).doubleValue();
 * </pre>
 *
 * @author Mutsunori Banbara (banbara@kobe-u.ac.jp)
 * @author Naoyuki Tamura (tamura@kobe-u.ac.jp)
 * @version 1.0
*/
public class DoubleTerm extends NumberTerm {
    /** Holds a <code>double</code> value that this <code>DoubleTerm</code> represents. */
    protected double val;

    /**
     * Constructs a new Prolog floating point number 
     * that represents the specified <code>double</code> value.
     */
    public DoubleTerm(double i) { val = i; }

    /**
     * Returns the value of <code>val</code>.
     * @see #val
     */
    public double value() { return val; }

    @Override
    public int type() {
      return TYPE_DOUBLE;
    }

    public boolean unify(Term t, Trail trail) {
	if (t instanceof VariableTerm)
	    return ((VariableTerm)t).unify(this, trail);
	if (! (t instanceof DoubleTerm))
	    return false;
	return this.val == ((DoubleTerm)t).value();
    }

    public String name() { return ""; }

    /** 
     * @return the <code>boolean</code> whose value is
     * <code>convertible(Double.class, type)</code>.
     * @see Term#convertible(Class, Class)
     */
    public boolean convertible(Class type) { return convertible(Double.class, type); }

    /** 
     * Returns a <code>java.lang.Double</code> corresponds to this <code>DoubleTerm</code>
     * according to <em>Prolog Cafe interoperability with Java</em>.
     * @return a <code>java.lang.Double</code> object equivalent to
     * this <code>DoubleTerm</code>.
     */
    public Object toJava() { return Double.valueOf(val); }

    /* Object */
    /** Returns a string representation of this <code>DoubleTerm</code>. */
    public String toString() { return Double.toString(this.val); }

    /**
     * Checks <em>term equality</em> of two terms.
     * The result is <code>true</code> if and only if the argument is an instance of
     * <code>DoubleTerm</code> and has the same <code>double</code> value as this object.
     * @param obj the object to compare with. This must be dereferenced.
     * @return <code>true</code> if the given object represents a Prolog floating
     * point number equivalent to this <code>DoubleTerm</code>, false otherwise.
     * @see #compareTo
    */
    public boolean equals(Object obj) {
	if (! (obj instanceof DoubleTerm))
	    return false;
	return Double.doubleToLongBits(this.val) == Double.doubleToLongBits(((DoubleTerm)obj).val);
    }

    public int hashCode() {
	long bits = Double.doubleToLongBits(this.val);
	return (int)(bits ^ (bits >>> 32));
    }

    /* Comparable */
    /** 
     * Compares two terms in <em>Prolog standard order of terms</em>.<br>
     * It is noted that <code>t1.compareTo(t2) == 0</code> has the same
     * <code>boolean</code> value as <code>t1.equals(t2)</code>.
     * @param anotherTerm the term to compared with. It must be dereferenced.
     * @return the value <code>0</code> if two terms are identical; 
     * a value less than <code>0</code> if this term is <em>before</em> the <code>anotherTerm</code>;
     * and a value greater than <code>0</code> if this term is <em>after</em> the <code>anotherTerm</code>.
     */
    public int compareTo(Term anotherTerm) { // anotherTerm must be dereferenced
	if (anotherTerm instanceof VariableTerm)
	    return AFTER;
	if (! (anotherTerm instanceof DoubleTerm))
	    return BEFORE;
	return Double.compare(this.val, ((DoubleTerm)anotherTerm).value());
    }

    /* NumberTerm */
    public int intValue() { return (int)val; }

    public long longValue() { return (long)val; }

    public double doubleValue() { return val; }

    public int arithCompareTo(NumberTerm t) {
	return Double.compare(this.val, t.doubleValue());
    }

    public NumberTerm abs() { return new DoubleTerm(Math.abs(this.val)); }

    public NumberTerm acos() { return new DoubleTerm(Math.acos(this.val)); }

    public NumberTerm add(NumberTerm t) { return new DoubleTerm(this.val + t.doubleValue()); }

    /** 
     * Throws a <code>type_error</code>.
     * @exception IllegalTypeException
     */
    public NumberTerm and(NumberTerm t) { throw new IllegalTypeException("integer", this); }
    //    public NumberTerm and(NumberTerm t) { return new IntegerTerm(this.intValue() & t.intValue()); }

    public NumberTerm asin() { return new DoubleTerm(Math.asin(this.val)); }

    public NumberTerm atan() { return new DoubleTerm(Math.atan(this.val)); }

    public NumberTerm ceil() { return new IntegerTerm((int) Math.ceil(this.val)); }

    public NumberTerm cos() { return new DoubleTerm(Math.cos(this.val)); }

    /** 
     * @exception EvaluationException if the given argument
     * <code>NumberTerm</code> represents <coe>0</code>.
     */
    public NumberTerm divide(NumberTerm t) { 
	if (t.doubleValue() == 0)
	    throw new EvaluationException("zero_divisor");
	return new DoubleTerm(this.val / t.doubleValue());
    }

    public NumberTerm exp() { return new DoubleTerm(Math.exp(this.val)); }

    public NumberTerm floatIntPart() { 
	return new DoubleTerm(Math.signum(this.val) * Math.floor(Math.abs(this.val)));
    }

    public NumberTerm floatFractPart() { 
	return new DoubleTerm(this.val - Math.signum(this.val) * Math.floor(Math.abs(this.val)));
    }

    public NumberTerm floor() { return new IntegerTerm((int) Math.floor(this.val)); }

    /** 
     * Throws a <code>type_error</code>.
     * @exception IllegalTypeException
     */
    public NumberTerm intDivide(NumberTerm t) { throw new IllegalTypeException("integer", this); }
    //    public NumberTerm intDivide(NumberTerm t) {	return new IntegerTerm((int)(this.intValue() / t.intValue())); }

    /** 
     * @exception EvaluationException if this object represents <coe>0</code>.
     */
    public NumberTerm log() { 
	if (this.val == 0)
	    throw new EvaluationException("undefined");
	return new DoubleTerm(Math.log(this.val)); 
    }

    public NumberTerm max(NumberTerm t) { return new DoubleTerm(Math.max(this.val, t.doubleValue())); }

    public NumberTerm min(NumberTerm t) { return new DoubleTerm(Math.min(this.val, t.doubleValue())); }

    /** 
     * Throws a <code>type_error</code>.
     * @exception IllegalTypeException
     */
    public NumberTerm mod(NumberTerm t) { throw new IllegalTypeException("integer", this); }
    //    public NumberTerm mod(NumberTerm t) { return new IntegerTerm(this.intValue() % t.intValue()); }

    public NumberTerm multiply(NumberTerm t) { return new DoubleTerm(this.val * t.doubleValue()); }

    public NumberTerm negate() { return new DoubleTerm(- this.val); }

    /** 
     * Throws a <code>type_error</code>.
     * @exception IllegalTypeException
     */
    public NumberTerm not() { throw new IllegalTypeException("integer", this); }
    //    public NumberTerm not() { return new IntegerTerm(~ this.intValue()); }

    /** 
     * Throws a <code>type_error</code>.
     * @exception IllegalTypeException
     */
    public NumberTerm or(NumberTerm t) { throw new IllegalTypeException("integer", this); }
    //    public NumberTerm or(NumberTerm t) { return new IntegerTerm(this.intValue() | t.intValue()); }

    public NumberTerm pow(NumberTerm t) { return new DoubleTerm(Math.pow(this.val, t.doubleValue())); }

    public NumberTerm rint() { return new DoubleTerm(Math.rint(this.val)); }

    public NumberTerm round() { return new IntegerTerm((int) Math.round(this.val)); }

    /** 
     * Throws a <code>type_error</code>.
     * @exception IllegalTypeException
     */
    public NumberTerm shiftLeft(NumberTerm t) { throw new IllegalTypeException("integer", this); }

    /** 
     * Throws a <code>type_error</code>.
     * @exception IllegalTypeException
     */
    public NumberTerm shiftRight(NumberTerm t) { throw new IllegalTypeException("integer", this); }

    public NumberTerm signum() {return new DoubleTerm(Math.signum(this.val)); }
 
    public NumberTerm sin() { return new DoubleTerm(Math.sin(this.val)); }

    /** 
     * @exception EvaluationException if this object represents
     * a floating point number less than <coe>0</code>.
     */
    public NumberTerm sqrt() { 
	if (this.val < 0)
	    throw new EvaluationException("undefined");
	return new DoubleTerm(Math.sqrt(this.val)); 
    }

    public NumberTerm subtract(NumberTerm t) { return new DoubleTerm(this.val - t.doubleValue()); }

    public NumberTerm tan() { return new DoubleTerm(Math.tan(this.val)); }

    public NumberTerm toDegrees() { return new DoubleTerm(Math.toDegrees(this.val)); }

    public NumberTerm toFloat() { return this; }

    public NumberTerm toRadians() { return new DoubleTerm(Math.toRadians(this.val)); }

    public NumberTerm truncate() { 
	if (this.val >= 0)
	    return new IntegerTerm((int) Math.floor(this.val));
	else 
	    return new IntegerTerm((int) (-1 * Math.floor(Math.abs(this.val))));
    }

    /** 
     * Throws a <code>type_error</code>.
     * @exception IllegalTypeException
     */
    public NumberTerm xor(NumberTerm t) { throw new IllegalTypeException("integer", this); }
}
