import java.io.PrintWriter;

/**
 * the wrapper class of int
 *
 * @author Hanhua Feng - hf2048@columbia.edu
 * @version $Id: MxInt.java,v 1.13 2003/05/12 23:44:34 hanhua Exp $
 */
class MxInt extends MxDataType {
    int var;

    public MxInt( int x ) {
        var = x;
    }

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

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

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

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

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

    public MxDataType plus( MxDataType b ) {
        if ( b instanceof MxInt )
            return new MxInt( var + intValue(b) );
        return new MxDouble( var + MxDouble.doubleValue(b) );
    }

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

    public MxDataType minus( MxDataType b ) {
        if ( b instanceof MxInt )
            return new MxInt( var - intValue(b) );
        return new MxDouble( var - MxDouble.doubleValue(b) );
    }
    
    public MxDataType sub( MxDataType b ) {
        var -= intValue( b );
        return this;
    }

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

    public MxDataType mul( MxDataType b ) {
        var *= intValue( 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 / (double)var ) );
        }
        
        if ( b instanceof MxInt )
            return new MxInt( var / intValue(b) );
        return new MxDouble( var / MxDouble.doubleValue(b) );
    }

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

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

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

    public MxDataType modulus( MxDataType b ) {
        if ( b instanceof MxInt )
            return new MxInt( var % intValue(b) );
        return new MxDouble( var % MxDouble.doubleValue(b) );
    }


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

    public MxDataType gt( MxDataType b ) {
        if ( b instanceof MxInt )
            return new MxBool( var > intValue(b) );
        return b.lt( this );
    }

    public MxDataType ge( MxDataType b ) {
        if ( b instanceof MxInt )
            return new MxBool( var >= intValue(b) );
        return b.le( this );
    }

    public MxDataType lt( MxDataType b ) {
        if ( b instanceof MxInt )
            return new MxBool( var < intValue(b) );
        return b.gt( this );
    }

    public MxDataType le( MxDataType b ) {
        if ( b instanceof MxInt )
            return new MxBool( var <= intValue(b) );
        return b.ge( this );
    }

    public MxDataType eq( MxDataType b ) {
        if ( b instanceof MxInt )
            return new MxBool( var == intValue(b) );
        return b.eq( this );
    }

    public MxDataType ne( MxDataType b ) {
        if ( b instanceof MxInt )
            return new MxBool( var != intValue(b) );
        return b.ne( this );
    }    
}
