

import java.util.Random;
import java.io.IOException;
import jamaica.*;

/** The internal functions: MxInternalFunction.java is generated by
 * MxInternalFunction.m4
 *
 * @author Hanhua Feng - hf2048@columbia.edu
 * @version $Id: MxInternalFunction.m4,v 1.13 2003/05/13 23:25:22 hanhua Exp $
 */
class MxInternalFunction {
    static Random random = new Random();
    static int[] rgbtable = Painter.colorMap( Painter.CM_GRAYSCALE );
    static int defcolor = 0;
    static Painter painter = null;
    static Plotter plotter = null;

    /* if there is no rgbtable, generate an length-1 table from defcolor */
    private static int[] getRGBTable() {
        if ( null != rgbtable )
            return rgbtable;
        return new int[]{ defcolor };
    }


    final static int f_print = 0;
    final static int f_what = 1;
    final static int f_plot = 2;
    final static int f_oplot = 3;
    final static int f_paint = 4;
    final static int f_opaint = 5;
    final static int f_colormap = 6;
    final static int f_color = 7;
    final static int f_load = 8;
    final static int f_save = 9;
    final static int f_width = 10;
    final static int f_height = 11;
    final static int f_random = 12;
    final static int f_zeros = 13;
    final static int f_eye = 14;
    final static int f_indgen = 15;
    final static int f_inv = 16;
    final static int f_det = 17;
    final static int f_flip = 18;
    final static int f_mirror = 19;
    final static int f_min = 20;
    final static int f_max = 21;
    final static int f_mul = 22;
    final static int f_div = 23;
    final static int f_count = 24;
    final static int f_round = 25;
    final static int f_floor = 26;
    final static int f_ceil = 27;
    final static int f_int = 28;
    final static int f_abs = 29;
    final static int f_sqrt = 30;
    final static int f_exp = 31;
    final static int f_log = 32;
    final static int f_pow = 33;
    final static int f_sin = 34;
    final static int f_cos = 35;
    final static int f_tan = 36;
    final static int f_asin = 37;
    final static int f_acos = 38;
    final static int f_atan  = 39;

    public static void register( MxSymbolTable st ) {

              st.put( "print", new MxFunction( null, f_print ) ); 
              st.put( "what", new MxFunction( null, f_what ) ); 
              st.put( "plot", new MxFunction( null, f_plot ) ); 
              st.put( "oplot", new MxFunction( null, f_oplot ) ); 
              st.put( "paint", new MxFunction( null, f_paint ) ); 
              st.put( "opaint", new MxFunction( null, f_opaint ) ); 
              st.put( "colormap", new MxFunction( null, f_colormap ) ); 
              st.put( "color", new MxFunction( null, f_color ) ); 
              st.put( "load", new MxFunction( null, f_load ) ); 
              st.put( "save", new MxFunction( null, f_save ) ); 
              st.put( "width", new MxFunction( null, f_width ) ); 
              st.put( "height", new MxFunction( null, f_height ) ); 
              st.put( "random", new MxFunction( null, f_random ) ); 
              st.put( "zeros", new MxFunction( null, f_zeros ) ); 
              st.put( "eye", new MxFunction( null, f_eye ) ); 
              st.put( "indgen", new MxFunction( null, f_indgen ) ); 
              st.put( "inv", new MxFunction( null, f_inv ) ); 
              st.put( "det", new MxFunction( null, f_det ) ); 
              st.put( "flip", new MxFunction( null, f_flip ) ); 
              st.put( "mirror", new MxFunction( null, f_mirror ) ); 
              st.put( "min", new MxFunction( null, f_min ) ); 
              st.put( "max", new MxFunction( null, f_max ) ); 
              st.put( "mul", new MxFunction( null, f_mul ) ); 
              st.put( "div", new MxFunction( null, f_div ) ); 
              st.put( "count", new MxFunction( null, f_count ) ); 
              st.put( "round", new MxFunction( null, f_round ) ); 
              st.put( "floor", new MxFunction( null, f_floor ) ); 
              st.put( "ceil", new MxFunction( null, f_ceil ) ); 
              st.put( "int", new MxFunction( null, f_int ) ); 
              st.put( "abs", new MxFunction( null, f_abs ) ); 
              st.put( "sqrt", new MxFunction( null, f_sqrt ) ); 
              st.put( "exp", new MxFunction( null, f_exp ) ); 
              st.put( "log", new MxFunction( null, f_log ) ); 
              st.put( "pow", new MxFunction( null, f_pow ) ); 
              st.put( "sin", new MxFunction( null, f_sin ) ); 
              st.put( "cos", new MxFunction( null, f_cos ) ); 
              st.put( "tan", new MxFunction( null, f_tan ) ); 
              st.put( "asin", new MxFunction( null, f_asin ) ); 
              st.put( "acos", new MxFunction( null, f_acos ) ); 
              st.put( "atan ", new MxFunction( null, f_atan  ) ); 
        st.put( "E", new MxDouble( Math.E ) );
        st.put( "PI", new MxDouble( Math.PI ) );
    }

    private static boolean isIntList( MxDataType[] params ){
        for ( int i=0; i<params.length; i++ )
            if ( ! ( params[i] instanceof MxInt ) )
                return false;
        return true;
    }

    public static MxDataType run( MxSymbolTable st,
                                  int id, MxDataType[] params ) {
        switch ( id )
        {
        case f_print:
            for ( int i=0; i<params.length; i++ )
                params[i].print();
            return null;

        case f_what:
            if ( params.length > 0 )
            {
                for ( int i=0; i<params.length; i++ )
                        params[i].what();
            }
            else
                st.what();
            return null;

        case f_paint:
            if ( params.length != 1 && params.length != 3 )
                throw new MxException( "paint() accepts 1 or 3  parameter(s)" );
            if ( !( params[0] instanceof MxMatrix ) )
                throw new MxException( "Only matrix can be drawn" );
            painter = Painter.create( "Mx Painter", 100, 100 );
            if ( 1 == params.length )
                painter.draw( ((MxMatrix)params[0]).mat, getRGBTable() );
            else
                painter.draw( ((MxMatrix)params[0]).mat, 
                    MxDouble.doubleValue( params[1] ),
                    MxDouble.doubleValue( params[2] ), getRGBTable() );
            return params[0];

        case f_opaint:
            if ( null == painter )
                throw new MxException( "No previous painting window" );
            if ( 0 == params.length )
                throw new MxException( "opaint() accepts 1 or more  parameter(s)" );
            if ( !( params[0] instanceof MxMatrix ) )
                throw new MxException( "Only matrix can be drawn" );
            BitArray bmk = null;
            double min = 0.0, max = 0.0;
            int xpos = 0, ypos = 0;
            int offset = 1;
            if ( offset < params.length 
                 && ( params[offset] instanceof MxBitArray ) )
                bmk = ((MxBitArray)params[offset++]).ba;

            if ( offset < params.length-1 )
            {
                xpos = MxInt.intValue( params[offset++] );
                ypos = MxInt.intValue( params[offset++] );
            }
            if ( offset < params.length-1 )
            {
                min = MxDouble.doubleValue( params[offset++] );
                max = MxDouble.doubleValue( params[offset++] );
            }
            if ( offset < params.length )
                throw new MxException( "Additional arguments" );
            if ( max > min )
                painter.overdraw( ((MxMatrix)params[0]).mat, bmk, min, max,
                                   getRGBTable(), xpos, ypos );
            else
                painter.overdraw( ((MxMatrix)params[0]).mat, bmk, 
                                  getRGBTable(), xpos, ypos );
            return params[0];

        case f_plot:
            if ( 1 != params.length && 2 != params.length )
                throw new MxException( "plot() accepts 1-2  parameter(s)" );;
            if ( !( params[0] instanceof MxMatrix ) )
                throw new MxException( "First arg should be a matrix" );
            plotter = Plotter.create( "Mx Plotter", 640, 480 );
            if ( 2 == params.length )
            {
                if ( !( params[1] instanceof MxMatrix ) )
                    throw new MxException( "Second arg should be a matrix" );
                Matrix mat = ((MxMatrix)params[1]).mat;
                double[] minmax = new double[6];
                minmax[0] = mat.get(0,0);
                minmax[1] = mat.get(1,0);
                minmax[2] = mat.get(0,1);
                minmax[3] = mat.get(1,1);
                if ( mat.width() >= 3 )
                {
                    minmax[4] = mat.get(0,2);
                    minmax[5] = mat.get(1,2);
                }
                plotter.draw( ((MxMatrix)params[0]).mat, 
                              minmax, defcolor, rgbtable );
            }
            else
                plotter.draw( ((MxMatrix)params[0]).mat, defcolor, rgbtable );
            return params[0];

        case f_color:
            if ( params.length != 3  )
                throw new MxException( "colors() accepts 3   parameter(s)" );;
            defcolor = Painter.color( MxDouble.doubleValue( params[0] ),
                                      MxDouble.doubleValue( params[1] ),
                                      MxDouble.doubleValue( params[2] ) );
            return null;

        case f_colormap:
            if ( 0 == params.length )
            {
                rgbtable = null;
                return null;
            }

            if ( params.length != 1  )
                throw new MxException( "colors() accepts 1   parameter(s)" );;
            if ( params[0] instanceof MxMatrix )
                rgbtable = Painter.colorMap( ((MxMatrix)params[0]).mat );
            else
                rgbtable = Painter.colorMap( MxInt.intValue( params[0] ) );
            return null;

        case f_load:
            if ( 4 != params.length && 5 != params.length )
                throw new MxException( "load() accepts 4-5  parameter(s)" );
            if ( ! (params[0] instanceof MxString 
                || params[1] instanceof MxString ) )
                throw new MxException( "First two args should be strings" );

            Matrix mat;
            try 
            {
                if ( params.length == 4 )
                    mat = Matrix.load( 
                        ((MxString)params[0]).var,
                        MxInterpreter.getDataType(((MxString)params[1]).var),
                        MxInt.intValue( params[2] ), 
                        MxInt.intValue( params[3] ) );
                else
                    mat = Matrix.load( ((MxString)params[0]).var,
                        MxInterpreter.getDataType(((MxString)params[1]).var),
                        MxInt.intValue( params[2] ), 
                        MxInt.intValue( params[3] ),
                        MxInt.intValue( params[4] ) );
            }
            catch ( IOException e )
            {
                throw new MxException( "I/O Exception:" + e );
            }

            if ( null == mat )
                throw new MxException( "File not found: " 
                                       + ((MxString)params[0]).var );
            return new MxMatrix( mat );

        case f_save:
            if ( 3 != params.length && 4 != params.length )
                throw new MxException( "save() accepts 3-4  parameter(s)" );
            if ( ! (params[0] instanceof MxMatrix) )
                throw new MxException( "Arg 1 should be a matrix" );
            if ( ! (params[1] instanceof MxString 
                || params[2] instanceof MxString ) )
                throw new MxException( "Args 2 and 3 should be strings" );
            try
            {
                if ( params.length == 3 )
                    ((MxMatrix)params[0]).mat.save(
                        ((MxString)params[1]).var,
                        MxInterpreter.getDataType(((MxString)params[2]).var) );
                else
                    ((MxMatrix)params[0]).mat.save(
                        ((MxString)params[1]).var,
                        MxInterpreter.getDataType( ((MxString)params[2]).var),
                        MxInt.intValue( params[3] ) );
            }
            catch ( IOException e )
            {
                throw new MxException( "I/O Exception:" + e );
            }
            return params[0];

        case f_width:
            if ( params.length != 1  )
                throw new MxException( "width() accepts 1   parameter(s)" );;
            if ( params[0] instanceof MxMatrix )
                return new MxInt( ((MxMatrix)params[0]).mat.width () );
            return new MxInt( 0 );

        case f_height:
            if ( params.length != 1  )
                throw new MxException( "height() accepts 1   parameter(s)" );;
            if ( params[0] instanceof MxMatrix )
                return new MxInt( ((MxMatrix)params[0]).mat.height () );
            return new MxInt( 0 );


        case f_random:
            if ( 0 == params.length )
                return new MxDouble( random.nextDouble() );
            if ( 1 == params.length )
            {
                if ( params[0] instanceof MxDouble )
                    return new MxDouble( random.nextDouble()
                                         * MxDouble.doubleValue( params[0] ) );

                if ( params[0] instanceof MxInt )
                    return new MxInt( random.nextInt( 
                                          MxInt.intValue( params[0] ) ) );
            }
            else if ( 2 == params.length )
                return new MxMatrix( Matrix.random( 
                                         MxInt.intValue( params[0] ),
                                         MxInt.intValue( params[1] ) ) );
            throw new MxException( "random() accepts 0-2  parameter(s)" );

        case f_zeros:
            if ( params.length != 2  )
                throw new MxException( "zeros() accepts 2   parameter(s)" );;
            return new MxMatrix( 
                new Matrix( MxInt.intValue( params[0] ), 
                            MxInt.intValue( params[1] ) ) );

        case f_eye:
            if ( params.length != 1  )
                throw new MxException( "eye() accepts 1   parameter(s)" );;
            return new MxMatrix( Matrix.eye( MxInt.intValue( params[0] ) ) );

        case f_indgen:
            if ( params.length != 5  )
                throw new MxException( "indgen() accepts 5   parameter(s)" );;;
            return new MxMatrix( Matrix.indgen(
                MxInt.intValue( params[0] ),
                MxInt.intValue( params[1] ),
                MxDouble.doubleValue( params[2] ),
                MxDouble.doubleValue( params[3] ),
                MxDouble.doubleValue( params[4] ) ) );

        case f_inv:
            if ( params.length != 1  )
                throw new MxException( "inv() accepts 1   parameter(s)" );;
            if ( ! (params[0] instanceof MxMatrix ) )
                return params[0].error( "inv" );
            return new MxMatrix ( ((MxMatrix)params[0]).mat.invert() );

        case f_det:
            if ( params.length != 1  )
                throw new MxException( "inv() accepts 1   parameter(s)" );;
            if ( ! (params[0] instanceof MxMatrix ) )
                return params[0].error( "det" );
            return new MxDouble ( ((MxMatrix)params[0]).mat.det() );

        case f_flip:
            if ( params.length != 1  )
                throw new MxException( "inv() accepts 1   parameter(s)" );;
            if ( ! (params[0] instanceof MxMatrix ) )
                return params[0].error( "flip" );
            return new MxMatrix ( ((MxMatrix)params[0]).mat.flip() );

        case f_mirror:
            if ( params.length != 1  )
                throw new MxException( "inv() accepts 1   parameter(s)" );;
            if ( ! (params[0] instanceof MxMatrix ) )
                return params[0].error( "mirror" );
            return new MxMatrix ( ((MxMatrix)params[0]).mat.mirror() );


        case f_min:
            if ( params.length > 0 )
            {
                if ( isIntList( params ) )
                {
                    int x = MxInt.intValue( params[0] );
                    for ( int i=1; i<params.length; i++ )
                    {
                        int y = MxInt.intValue( params[i] );
                        if ( y <  x )
                            x = y;
                    }
                    return new MxInt( x );
                }

                double x = ( (params[0] instanceof MxMatrix)?
                             ((MxMatrix)params[0]).mat.min()
                             : MxDouble.doubleValue( params[0] ) );
                for ( int i=1; i<params.length; i++ )
                {
                    double y = ( (params[i] instanceof MxMatrix)?
                                 ((MxMatrix)params[i]).mat.min()
                                 : MxDouble.doubleValue( params[i] ) );
                    if ( y <  x )
                        x = y;
                }
                return new MxDouble( x );
            }
            throw new MxException( "min() accepts 1  parameter(s)" );

        case f_max:
            if ( params.length > 0 )
            {
                if ( isIntList( params ) )
                {
                    int x = MxInt.intValue( params[0] );
                    for ( int i=1; i<params.length; i++ )
                    {
                        int y = MxInt.intValue( params[i] );
                        if ( y >  x )
                            x = y;
                    }
                    return new MxInt( x );
                }

                double x = ( (params[0] instanceof MxMatrix)?
                             ((MxMatrix)params[0]).mat.max()
                             : MxDouble.doubleValue( params[0] ) );
                for ( int i=1; i<params.length; i++ )
                {
                    double y = ( (params[i] instanceof MxMatrix)?
                                 ((MxMatrix)params[i]).mat.max()
                                 : MxDouble.doubleValue( params[i] ) );
                    if ( y >  x )
                        x = y;
                }
                return new MxDouble( x );
            }
            throw new MxException( "max() accepts 1  parameter(s)" );


        case f_mul:
            if ( params.length != 2  )
                throw new MxException( "mul() accepts 2   parameter(s)" );;
            if ( params[0] instanceof MxMatrix 
                 && params[1] instanceof MxMatrix )
            {
                return new MxMatrix( 
                    ((MxMatrix)params[0]).mat.etimes ( 
                        ((MxMatrix)params[1]).mat ) );
            }
            throw new MxException( "mul: arguments should be matricies" );

        case f_div:
            if ( params.length != 2  )
                throw new MxException( "div() accepts 2   parameter(s)" );;
            if ( params[0] instanceof MxMatrix 
                 && params[1] instanceof MxMatrix )
            {
                return new MxMatrix( 
                    ((MxMatrix)params[0]).mat.edivide ( 
                        ((MxMatrix)params[1]).mat ) );
            }
            throw new MxException( "div: arguments should be matricies" );


        case f_pow:
            if ( params.length != 2  )
                throw new MxException( "$1() accepts 2   parameter(s)" );;
            double pwr = MxDouble.doubleValue( params[1] );

            if ( params[0] instanceof MxMatrix )
            {
                Matrix p = ((MxMatrix)params[0]).mat;
                int m = p.height(), n = p.width();
                Matrix x = new Matrix( m, n );
                for ( int j=0; j<n; j++ )
                    for ( int i=0; i<m; i++ )
                        x.set( i, j, Math.pow( p.get(i,j), pwr ) );
                return new MxMatrix( x );
            }
            return new MxDouble( 
                Math.pow( MxDouble.doubleValue( params[0] ), pwr ) );

        case f_count:
            if ( params.length != 1  )
                throw new MxException( "$1() accepts 1   parameter(s)" );;;
            if ( params[0] instanceof MxBitArray )
                return new MxInt( ((MxBitArray)params[0]).ba.count() );
            throw new MxException( "count() accepts one bitmask argument" );

        case f_round:
            if ( params.length != 1  )
                throw new MxException( "round() accepts 1   parameter(s)" );;
            if ( params[0] instanceof MxMatrix )
            {
                Matrix p = ((MxMatrix)params[0]).mat;
                int m = p.height(), n = p.width();
                Matrix x = new Matrix( m, n );
                for ( int j=0; j<n; j++ )
                    for ( int i=0; i<m; i++ )
                        x.set( i, j, Math.round ( p.get(i,j) ) );
                return new MxMatrix( x );
            }
            return new MxDouble( 
                Math.round ( MxDouble.doubleValue( params[0] ) ) );

        case f_ceil:
            if ( params.length != 1  )
                throw new MxException( "ceil() accepts 1   parameter(s)" );;
            if ( params[0] instanceof MxMatrix )
            {
                Matrix p = ((MxMatrix)params[0]).mat;
                int m = p.height(), n = p.width();
                Matrix x = new Matrix( m, n );
                for ( int j=0; j<n; j++ )
                    for ( int i=0; i<m; i++ )
                        x.set( i, j, Math.ceil ( p.get(i,j) ) );
                return new MxMatrix( x );
            }
            return new MxDouble( 
                Math.ceil ( MxDouble.doubleValue( params[0] ) ) );

        case f_floor:
            if ( params.length != 1  )
                throw new MxException( "floor() accepts 1   parameter(s)" );;
            if ( params[0] instanceof MxMatrix )
            {
                Matrix p = ((MxMatrix)params[0]).mat;
                int m = p.height(), n = p.width();
                Matrix x = new Matrix( m, n );
                for ( int j=0; j<n; j++ )
                    for ( int i=0; i<m; i++ )
                        x.set( i, j, Math.floor ( p.get(i,j) ) );
                return new MxMatrix( x );
            }
            return new MxDouble( 
                Math.floor ( MxDouble.doubleValue( params[0] ) ) );

        case f_abs:
            if ( params.length != 1  )
                throw new MxException( "abs() accepts 1   parameter(s)" );;
            if ( params[0] instanceof MxMatrix )
            {
                Matrix p = ((MxMatrix)params[0]).mat;
                int m = p.height(), n = p.width();
                Matrix x = new Matrix( m, n );
                for ( int j=0; j<n; j++ )
                    for ( int i=0; i<m; i++ )
                        x.set( i, j, Math.abs ( p.get(i,j) ) );
                return new MxMatrix( x );
            }
            return new MxDouble( 
                Math.abs ( MxDouble.doubleValue( params[0] ) ) );

        case f_sqrt:
            if ( params.length != 1  )
                throw new MxException( "sqrt() accepts 1   parameter(s)" );;
            if ( params[0] instanceof MxMatrix )
            {
                Matrix p = ((MxMatrix)params[0]).mat;
                int m = p.height(), n = p.width();
                Matrix x = new Matrix( m, n );
                for ( int j=0; j<n; j++ )
                    for ( int i=0; i<m; i++ )
                        x.set( i, j, Math.sqrt ( p.get(i,j) ) );
                return new MxMatrix( x );
            }
            return new MxDouble( 
                Math.sqrt ( MxDouble.doubleValue( params[0] ) ) );

        case f_exp:
            if ( params.length != 1  )
                throw new MxException( "exp() accepts 1   parameter(s)" );;
            if ( params[0] instanceof MxMatrix )
            {
                Matrix p = ((MxMatrix)params[0]).mat;
                int m = p.height(), n = p.width();
                Matrix x = new Matrix( m, n );
                for ( int j=0; j<n; j++ )
                    for ( int i=0; i<m; i++ )
                        x.set( i, j, Math.exp ( p.get(i,j) ) );
                return new MxMatrix( x );
            }
            return new MxDouble( 
                Math.exp ( MxDouble.doubleValue( params[0] ) ) );

        case f_log:
            if ( params.length != 1  )
                throw new MxException( "log() accepts 1   parameter(s)" );;
            if ( params[0] instanceof MxMatrix )
            {
                Matrix p = ((MxMatrix)params[0]).mat;
                int m = p.height(), n = p.width();
                Matrix x = new Matrix( m, n );
                for ( int j=0; j<n; j++ )
                    for ( int i=0; i<m; i++ )
                        x.set( i, j, Math.log ( p.get(i,j) ) );
                return new MxMatrix( x );
            }
            return new MxDouble( 
                Math.log ( MxDouble.doubleValue( params[0] ) ) );

        case f_sin:
            if ( params.length != 1  )
                throw new MxException( "sin() accepts 1   parameter(s)" );;
            if ( params[0] instanceof MxMatrix )
            {
                Matrix p = ((MxMatrix)params[0]).mat;
                int m = p.height(), n = p.width();
                Matrix x = new Matrix( m, n );
                for ( int j=0; j<n; j++ )
                    for ( int i=0; i<m; i++ )
                        x.set( i, j, Math.sin ( p.get(i,j) ) );
                return new MxMatrix( x );
            }
            return new MxDouble( 
                Math.sin ( MxDouble.doubleValue( params[0] ) ) );

        case f_cos:
            if ( params.length != 1  )
                throw new MxException( "cos() accepts 1   parameter(s)" );;
            if ( params[0] instanceof MxMatrix )
            {
                Matrix p = ((MxMatrix)params[0]).mat;
                int m = p.height(), n = p.width();
                Matrix x = new Matrix( m, n );
                for ( int j=0; j<n; j++ )
                    for ( int i=0; i<m; i++ )
                        x.set( i, j, Math.cos ( p.get(i,j) ) );
                return new MxMatrix( x );
            }
            return new MxDouble( 
                Math.cos ( MxDouble.doubleValue( params[0] ) ) );

        case f_tan:
            if ( params.length != 1  )
                throw new MxException( "tan() accepts 1   parameter(s)" );;
            if ( params[0] instanceof MxMatrix )
            {
                Matrix p = ((MxMatrix)params[0]).mat;
                int m = p.height(), n = p.width();
                Matrix x = new Matrix( m, n );
                for ( int j=0; j<n; j++ )
                    for ( int i=0; i<m; i++ )
                        x.set( i, j, Math.tan ( p.get(i,j) ) );
                return new MxMatrix( x );
            }
            return new MxDouble( 
                Math.tan ( MxDouble.doubleValue( params[0] ) ) );

        case f_asin:
            if ( params.length != 1  )
                throw new MxException( "asin() accepts 1   parameter(s)" );;
            if ( params[0] instanceof MxMatrix )
            {
                Matrix p = ((MxMatrix)params[0]).mat;
                int m = p.height(), n = p.width();
                Matrix x = new Matrix( m, n );
                for ( int j=0; j<n; j++ )
                    for ( int i=0; i<m; i++ )
                        x.set( i, j, Math.asin ( p.get(i,j) ) );
                return new MxMatrix( x );
            }
            return new MxDouble( 
                Math.asin ( MxDouble.doubleValue( params[0] ) ) );

        case f_acos:
            if ( params.length != 1  )
                throw new MxException( "acos() accepts 1   parameter(s)" );;
            if ( params[0] instanceof MxMatrix )
            {
                Matrix p = ((MxMatrix)params[0]).mat;
                int m = p.height(), n = p.width();
                Matrix x = new Matrix( m, n );
                for ( int j=0; j<n; j++ )
                    for ( int i=0; i<m; i++ )
                        x.set( i, j, Math.acos ( p.get(i,j) ) );
                return new MxMatrix( x );
            }
            return new MxDouble( 
                Math.acos ( MxDouble.doubleValue( params[0] ) ) );

        case f_atan:
            if ( params.length != 1  )
                throw new MxException( "atan() accepts 1   parameter(s)" );;
            if ( params[0] instanceof MxMatrix )
            {
                Matrix p = ((MxMatrix)params[0]).mat;
                int m = p.height(), n = p.width();
                Matrix x = new Matrix( m, n );
                for ( int j=0; j<n; j++ )
                    for ( int i=0; i<m; i++ )
                        x.set( i, j, Math.atan ( p.get(i,j) ) );
                return new MxMatrix( x );
            }
            return new MxDouble( 
                Math.atan ( MxDouble.doubleValue( params[0] ) ) );

 
        default:
            throw new MxException( "unknown internal function" );
        }
    }

}