import java.io.PrintWriter;

/**
 * The wrapper class for double
 *
 * @author Hanhua Feng - hf2048@columbia.edu
 * @version $Id: MxDouble.java,v 1.14 2003/05/15 19:49:45 hanhua Exp $
 */
class MxDouble extends MxDataType {
    double var;

    public MxDouble( double x ) {
        var = x;
    }

    public String typename() {
        return "double";
    }

    public MxDataType copy() {
        return new MxDouble( var );
    }    

    public static double doubleValue( MxDataType b ) {
        if ( b instanceof MxDouble )
            return ((MxDouble)b).var;
        if ( b instanceof MxInt )
            return (double) ((MxInt)b).var;
        if ( b instanceof MxMatrix && ((MxMatrix)b).demoteable() )
            return ((MxMatrix)b).mat.get(0,0);
        b.error( "cast to double" );
        return 0;
    }

    public void print( PrintWriter w ) {
        if ( name != null )
            w.print( name + " = " );
        w.println( Double.toString( var ) );
    }

    public MxDataType uminus() {
        return new MxDouble( -var );
    }

    public MxDataType plus( MxDataType b ) {
        return new MxDouble( var + doubleValue(b) );
    }

    public MxDataType add( MxDataType b ) {
        var += doubleValue( b );
        return this;
    }

    public MxDataType minus( MxDataType b ) {
        return new MxDouble( var - doubleValue(b) );
    }
    
    public MxDataType sub( MxDataType b ) {
        var -= doubleValue( b );
        return this;
    }

    public MxDataType times( MxDataType b ) {
        if ( b instanceof MxMatrix )
            return b.times( this );
        return new MxDouble( var * doubleValue(b) );
    }

    public MxDataType mul( MxDataType b ) {
        var *= doubleValue( b );
        return this;
    }

    public MxDataType lfracts( MxDataType b ) {
        if ( b instanceof MxMatrix && !((MxMatrix)b).demoteable() )
        {
            return new MxMatrix( 
                ((MxMatrix)b).mat.invert().selfmul( 1.0 / var ) );
        }
        
        return new MxDouble( var / doubleValue(b) );
    }

    public MxDataType rfracts( MxDataType b ) {
        return lfracts( b );
    }

    public MxDataType ldiv( MxDataType b ) {
        var /= doubleValue(b);
        return this;
    }

    public MxDataType rdiv( MxDataType b ) {
        return ldiv( b );
    }

    public MxDataType modulus( MxDataType b ) {
        return new MxDouble( var % doubleValue(b) );
    }


    public MxDataType rem( MxDataType b ) {
        var %= doubleValue( b );
        return this;
    }

    public MxDataType gt( MxDataType b ) {
        if ( b instanceof MxMatrix && !((MxMatrix)b).demoteable() )
            return b.lt( this );
        return new MxBool( var > doubleValue(b) );
    }

    public MxDataType ge( MxDataType b ) {
        if ( b instanceof MxMatrix && !((MxMatrix)b).demoteable() )
            return b.le( this );
        return new MxBool( var >= doubleValue(b) );
    }

    public MxDataType lt( MxDataType b ) {
        if ( b instanceof MxMatrix && !((MxMatrix)b).demoteable() )
            return b.gt( this );
        return new MxBool( var < doubleValue(b) );
    }

    public MxDataType le( MxDataType b ) {
        if ( b instanceof MxMatrix && !((MxMatrix)b).demoteable() )
            return b.ge( this );
        return new MxBool( var <= doubleValue(b) );
    }

    public MxDataType eq( MxDataType b ) {
        if ( b instanceof MxMatrix && !((MxMatrix)b).demoteable() )
            return b.eq( this );
        return new MxBool( var == doubleValue(b) );
    }

    public MxDataType ne( MxDataType b ) {
        if ( b instanceof MxMatrix && !((MxMatrix)b).demoteable() )
            return b.ne( this );
        return new MxBool( var != doubleValue(b) );
    }
}
