Back to index

wims  3.65+svn20090927
Function.java
Go to the documentation of this file.
00001 /*
00002  * @(#)Function.java
00003  * 
00004  * $Id: Function.java,v 1.24 2002/08/08 05:15:04 huaz Exp $
00005  *
00006  * Created on October 30, 2000, 10:29 AM
00007  */
00008 package SharpTools;
00009 import java.util.*;
00010 import java.io.*;
00011 
00024 public abstract class Function {    
00025 
00026     static private ParserException exception = new ParserException("#PARAM?");
00027     
00028     // whether the specified parameter node is an address range
00029     protected boolean isRange(Node param) {
00030        LinkedList exp = param.getExp();
00031        return exp.size() == 1 &&
00032            ((Node)exp.getFirst()).isType(Node.COLON);
00033            //((Node)param.getExp().getFirst()).isType(Node.COLON);
00034     }
00035 
00036     // return the first node of a specified parameter
00037     protected Node getFirst(Node param) {
00038        return (Node)param.getExp().getFirst();
00039     }    
00040 
00041     // whether this function has any parameter
00042     protected void checkParamsExist(Node func) throws ParserException {
00043        
00044        if (func.getParams().size()==0){
00045            throw exception;
00046        }
00047     }
00048     
00061     static protected float getSingleParameter(SharpTableModel table, Node node,
00062                                        int row, int col)
00063        throws ParserException {
00064        //     Node param = node.getNextParam();
00065        LinkedList params = node.getParams();
00066 
00067        if (params.size() != 1)
00068            throw new ParserException("#PARAM?");
00069 
00070        LinkedList exp = ((Node)params.getFirst()).getExp();
00071        
00072        return Formula.evaluate(table, exp, row, col).floatValue();
00073 
00074     }
00075 
00076     /*
00077      * This gets two float numbers of a parameter list, for functions
00078      * only accepting two parameters.
00079      * 
00080      * @param table the SharpTabelModel
00081      * @param node the formula unit
00082      * @param col the int column coordinate
00083      * @param row the int row coordinate
00084      * @return two float nubmers
00085      */
00086     /*
00087     static protected float[] getDoubleParameter(SharpTableModel table,
00088                                           Node node,
00089                                           int row, int col)
00090        throws ParserException {
00091        //     Node param = node.getNextParam();
00092        LinkedList params = node.getParams();
00093 
00094        if (params.size() != 2)
00095            throw new ParserException("#PARAM?");
00096 
00097        float[] values = new float[2];
00098        
00099        LinkedList exp = ((Node)params.getFirst()).getExp();
00100        values[0] = Formula.evaluate(table, exp, row, col).floatValue();
00101 
00102        exp = ((Node)params.getLast()).getExp();
00103        values[1] = Formula.evaluate(table, exp, row, col).floatValue();
00104 
00105        return values;
00106     }
00107     */
00118    public abstract Number evaluate(SharpTableModel table, Node node,  int row, int col) throws ParserException;
00119 
00123     public abstract String getUsage();
00124     
00128     public abstract String getDescription();
00129 
00136     public boolean requireParams() { return true; }
00137 }
00138 
00146 class FunctionSum extends Function {
00147     public Number evaluate(SharpTableModel table, Node node, int row, int col) throws ParserException {
00148     
00149        // requires parameters
00150        checkParamsExist(node);
00151        
00152        float sum = 0;
00153 
00154        LinkedList params = node.getParams();
00155        if (params != null) {
00156 
00157            // go over the parameters
00158            Iterator it = params.iterator();
00159 
00160            while (it.hasNext()) {
00161 
00162               // get this parameter
00163               Node exp = (Node)it.next();
00164 
00165               // if it's a range of cells
00166               if (isRange(exp)) {      
00167                   CellPoint[] addr =
00168                      getFirst(exp).getAddressRange(row, col);
00169                   // for a range, go over the whole range
00170                   for (int i = addr[0].getRow(); i <= addr[1].getRow(); i++)
00171                      for (int j = addr[0].getCol(); j <= addr[1].getCol(); j++)
00172                          // get the numeric value of that cell
00173                          sum += table.getNumericValueAt(i, j).floatValue();
00174               }
00175               else {
00176                   // evaluate this parameter's expression (sub-formula)
00177                   sum += Formula.evaluate(table, exp.getExp(), row, col).floatValue();
00178               }
00179            }
00180            
00181        }
00182        return (Number)(new Float(sum));
00183     }
00184 
00185     public String getUsage() {
00186        return "SUM(value1,value2,...)";
00187     }
00188     
00189     public String getDescription() {
00190        return SharpTools.translation.getProperty("sum_desc");
00191        //return "Adds all the numbers in a set of values.";
00192     }
00193 }
00194 
00195 
00202 class FunctionCount extends Function {
00203     
00204     public Number evaluate(SharpTableModel table, Node node,
00205                      int row, int col) throws ParserException {
00206 
00207        // requires parameters
00208        checkParamsExist(node);
00209 
00210        int count = 0;
00211 
00212        LinkedList params = node.getParams();
00213        
00214        if (params != null) {
00215 
00216            Iterator it = params.iterator();
00217 
00218            while (it.hasNext()) {
00219               // the first parameter
00220               Node exp = (Node)it.next();
00221               
00222               if (isRange(exp)) {
00223                   // if it's a range then count the number of cells
00224                   CellPoint[] addr =
00225                      getFirst(exp).getAddressRange(row, col);
00226                   count += (addr[1].getRow()-addr[0].getRow()+1) *
00227                      (addr[1].getCol()-addr[0].getCol()+1);
00228               }
00229               else {
00230                   // otherwise count one
00231                   count++;             
00232               }
00233            }
00234            
00235        }
00236        
00237        return new Integer(count);
00238     }
00239 
00240     public String getUsage() {
00241        return "COUNT(value1,value2,...)";
00242     }
00243     
00244     public String getDescription() {
00245        return SharpTools.translation.getProperty("count_desc");
00246        //return "Counts the number of cells that contain numbers and numbers within the list of arguments.";
00247     }
00248 }
00249 
00256 class FunctionAverage extends Function {
00257     
00258     public Number evaluate(SharpTableModel table, Node node,
00259                        int row, int col) throws ParserException {
00260        float sum = (new FunctionSum()).evaluate(table, node, row, col).
00261            floatValue();
00262        float nCells = (new FunctionCount()).evaluate(table, node, row, col).
00263            floatValue();
00264        return new Float(sum/nCells);
00265     }
00266 
00267     public String getUsage() {
00268        return "AVERAGE(value1,value2,...)";
00269     }
00270     
00271     public String getDescription() {
00272        return SharpTools.translation.getProperty("average_desc");
00273        //return "Returns the average (arithmetric mean) of its arguments.";
00274     }    
00275 }
00276 
00283 class FunctionMedian extends Function {
00284     
00285     public Number evaluate(SharpTableModel table, Node node,
00286                        int row, int col) throws ParserException {
00287        // requires parameters
00288        checkParamsExist(node);
00289 
00290        // get number of values
00291        int nCells = (int)(new FunctionCount()).
00292            evaluate(table, node, row, col).floatValue();
00293 
00294        float[] values = new float[nCells];
00295 
00296        // get all the values
00297        
00298        int index = 0;
00299        
00300        LinkedList params = node.getParams();
00301        
00302        if (params != null) {
00303 
00304            Iterator it = params.iterator();
00305 
00306            while (it.hasNext()) {
00307               // the first parameter
00308               Node exp = (Node)it.next();
00309               
00310               if (isRange(exp)) {
00311                   // if it's a range get each cell's value
00312                   CellPoint[] addr =
00313                      getFirst(exp).getAddressRange(row, col);
00314                   
00315                   for (int i = addr[0].getRow(); i <= addr[1].getRow(); i++)
00316                      for (int j = addr[0].getCol(); j <= addr[1].getCol(); j++){
00317                          values[index++] =
00318                             table.getNumericValueAt(i, j).floatValue();
00319                      }
00320               }
00321               else {
00322                   // otherwise get this expression's value
00323                   values[index++] =
00324                      Formula.evaluate(table, exp.getExp(), row, col).floatValue();
00325               }
00326            }
00327            
00328        }
00329 
00330        // sort the values array
00331        for (int m = 0; m < nCells-1; m++)
00332            for (int n = m; n < nCells-1; n++)
00333               if (values[m]>values[n]) {
00334                   float tmp = values[m];
00335                   values[m] = values[n];
00336                   values[n] = tmp;
00337               }
00338 
00339        // get the median
00340        int half = nCells/2;
00341        
00342        if (nCells != half*2)
00343            return new Float(values[half]);
00344        else
00345            return new Float((values[half-1]+values[half])/2);
00346     }
00347 
00348     public String getUsage() {
00349        return "MEDIAN(value1,value2,...)";
00350     }
00351     
00352     public String getDescription() {
00353        return SharpTools.translation.getProperty("median_desc");
00354        //return "Returns the median (value in the middle) of its arguments.";
00355     }    
00356 }
00357 
00364 class FunctionMin extends Function {
00365     
00366     public Number evaluate(SharpTableModel table, Node node,
00367                        int row, int col) throws ParserException {
00368        
00369        // requires parameters
00370        checkParamsExist(node);
00371        
00372        float min = Float.MAX_VALUE;
00373        LinkedList params = node.getParams();
00374        
00375        if (params != null) {
00376 
00377            Iterator it = params.iterator();
00378 
00379            while (it.hasNext()) {
00380 
00381               Node exp = (Node)it.next();
00382               
00383               if (isRange(exp)) {      
00384                   CellPoint[] addr =
00385                      getFirst(exp).getAddressRange(row, col);
00386                   
00387                   for (int i = addr[0].getRow(); i <= addr[1].getRow(); i++)
00388                      for (int j = addr[0].getCol(); j <= addr[1].getCol(); j++){
00389                          float value =
00390                             table.getNumericValueAt(i, j).floatValue();
00391                          if (value < min)
00392                             min = value;
00393                      }
00394               }
00395               else {
00396                   float value =
00397                      Formula.evaluate(table, exp.getExp(), row, col).floatValue();
00398                   if (value < min)
00399                      min = value;
00400               }
00401            }
00402            
00403        }
00404        
00405        return new Float(min);
00406     }
00407 
00408     public String getUsage() {
00409        return "MIN(value1,value2,...)";
00410     }
00411     
00412     public String getDescription() {
00413        return SharpTools.translation.getProperty("min_desc");
00414        //return "Returns the smallest number in a set of values.";
00415     }        
00416 }
00417 
00424 class FunctionMax extends Function {
00425      
00426     public Number evaluate(SharpTableModel table, Node node,
00427                        int row, int col) throws ParserException {
00428        
00429        // requires parameters
00430        checkParamsExist(node);
00431        
00432        float max = Float.MIN_VALUE;
00433        LinkedList params = node.getParams();
00434        
00435        if (params != null) {
00436 
00437            Iterator it = params.iterator();
00438 
00439            while (it.hasNext()) {
00440 
00441               Node exp = (Node)it.next();
00442               
00443               if (isRange(exp)) {      
00444                   CellPoint[] addr =
00445                      getFirst(exp).getAddressRange(row, col);
00446                   
00447                   for (int i = addr[0].getRow(); i <= addr[1].getRow(); i++)
00448                      for (int j = addr[0].getCol(); j <= addr[1].getCol(); j++){
00449                          float value =
00450                             table.getNumericValueAt(i, j).floatValue();
00451                          if (value > max)
00452                             max = value;
00453                      }
00454               }
00455               else {
00456                   float value =
00457                      Formula.evaluate(table, exp.getExp(), row, col).floatValue();
00458                   if (value > max)
00459                      max = value;
00460               }
00461            }
00462            
00463        }
00464        
00465        return new Float(max);
00466     }
00467 
00468 
00469     public String getUsage() {
00470        return "MAX(value1,value2,...)";
00471     }
00472     
00473     public String getDescription() {
00474        return SharpTools.translation.getProperty("max_desc");
00475        //return "Returns the largest number in a set of values.";
00476     }         
00477 }
00478 
00482 class FunctionRange extends Function {
00483 
00484     public Number evaluate(SharpTableModel table, Node node,
00485                        int row, int col) throws ParserException {
00486 
00487        float max = Formula.getFuncHandler("MAX").
00488            evaluate(table, node, row, col).
00489            floatValue();
00490        float min = Formula.getFuncHandler("MIN").
00491            evaluate(table, node, row, col).
00492            floatValue();    
00493        return new Float(max - min);
00494     }
00495 
00496 
00497     public String getUsage() {
00498        return "RANGE(value1,value2,...)";
00499     }
00500     
00501     public String getDescription() {
00502        return SharpTools.translation.getProperty("diff_desc");
00503 //     return "Returns the difference between MAX and MIN in a set of values.";
00504     }    
00505 }
00506 
00514 class FunctionAbs extends Function {
00515 
00516     public Number evaluate(SharpTableModel table, Node node,
00517                        int row, int col) throws ParserException {
00518        return new Float(Math.abs
00519                       (getSingleParameter(table, node, row, col)));
00520     }
00521 
00522     public String getUsage() {
00523        return "ABS(value)";
00524     }
00525     
00526     public String getDescription() {
00527        return SharpTools.translation.getProperty("abs_desc");
00528        //return "Returns the absolute value of a number.";
00529     }         
00530 }
00531 
00539 class FunctionSin extends Function {
00540 
00541     public Number evaluate(SharpTableModel table, Node node,
00542                        int row, int col) throws ParserException {
00543        return new Float(Math.sin
00544                       (getSingleParameter(table, node, row, col)));
00545     }
00546 
00547 
00548     public String getUsage() {
00549        return "SIN(value)";
00550     }
00551     
00552     public String getDescription() {
00553        return SharpTools.translation.getProperty("sin_desc");
00554        //return "Returns the sine of an angle.";
00555     }         
00556 }
00557 
00565 class FunctionCos extends Function {
00566 
00567     public Number evaluate(SharpTableModel table, Node node,
00568                        int row, int col) throws ParserException {
00569        
00570        return new Float(Math.cos
00571                       (getSingleParameter(table, node, row, col)));
00572     }
00573 
00574     public String getUsage() {
00575        return "COS(value)";
00576     }
00577     
00578     public String getDescription() {
00579        return SharpTools.translation.getProperty("cos_desc");
00580        //return "Returns the cosine of an angle.";
00581     }         
00582 }
00583 
00591 class FunctionTan extends Function {
00592 
00593     public Number evaluate(SharpTableModel table, Node node,
00594                        int row, int col) throws ParserException {
00595     
00596        return new Float(Math.tan
00597                       (getSingleParameter(table, node, row, col)));
00598     }
00599 
00600     public String getUsage() {
00601        return "TAN(value)";
00602     }
00603     
00604     public String getDescription() {
00605        return SharpTools.translation.getProperty("tan_desc");
00606        //return "Returns the tangent of an angle.";
00607     }    
00608 }
00609 
00617 class FunctionAsin extends Function {
00618 
00619     public Number evaluate(SharpTableModel table, Node node,
00620                        int row, int col) throws ParserException {
00621        return new Float(Math.asin
00622                       (getSingleParameter(table, node, row, col)));
00623     }
00624 
00625     public String getUsage() {
00626        return "ASIN(value)";
00627     }
00628     
00629     public String getDescription() {
00630        return SharpTools.translation.getProperty("asin_desc");
00631        //return "Returns the arcsine of a number in radians, in the range -Pi/2 to Pi/2.";
00632     }             
00633 }
00634 
00642 class FunctionAcos extends Function {
00643 
00644     public Number evaluate(SharpTableModel table, Node node,
00645                        int row, int col) throws ParserException {
00646 
00647        return new Float(Math.acos
00648                       (getSingleParameter(table, node, row, col)));
00649     }
00650 
00651     public String getUsage() {
00652        return "ACOS(value)";
00653     }
00654     
00655     public String getDescription() {
00656        return SharpTools.translation.getProperty("acos_desc");
00657        //return "Returns the arccosine of a number in radians, in the range 0 to Pi.";
00658     }                 
00659 }
00660 
00668 class FunctionAtan extends Function {
00669 
00670     public Number evaluate(SharpTableModel table, Node node,
00671                        int row, int col) throws ParserException {
00672 
00673        return new Float(Math.atan
00674                       (getSingleParameter(table, node, row, col)));
00675     }
00676 
00677     public String getUsage() {
00678        return "ATAN(value)";
00679     }
00680     
00681     public String getDescription() {
00682        return SharpTools.translation.getProperty("atan_desc");    
00683        //return "Returns the arctangent of a number in radians, in the range -Pi/2 to Pi/2.";
00684     }                 
00685 }
00686 
00691 class FunctionInt extends Function {
00692 
00693     public Number evaluate(SharpTableModel table, Node node,
00694                        int row, int col) throws ParserException {
00695 
00696        return new Float((int)getSingleParameter(table, node, row, col));
00697     }
00698 
00699     public String getUsage() {
00700        return "INT(value)";
00701     }
00702     
00703     public String getDescription() {
00704        return SharpTools.translation.getProperty("int_desc");
00705        //return "Returns the integer part of a number.";
00706     }                 
00707 }
00708 
00715 class FunctionRound extends Function {
00716 
00717     public Number evaluate(SharpTableModel table, Node node,
00718                        int row, int col) throws ParserException {
00719        
00720        return new Float(Math.round
00721                       (getSingleParameter(table, node, row, col)));
00722     }
00723 
00724     public String getUsage() {
00725        return "ROUND(value)";
00726     }
00727     
00728     public String getDescription() {
00729        return SharpTools.translation.getProperty("round_desc");
00730        //return "Returns the nearest integer of a number.";
00731     }
00732 }
00733 
00740 class FunctionSqrt extends Function {
00741 
00742     public Number evaluate(SharpTableModel table, Node node,
00743                        int row, int col) throws ParserException {
00744 
00745        return new Float(Math.sqrt
00746                       (getSingleParameter(table, node, row, col)));
00747     }
00748 
00749     public String getUsage() {
00750        return "SQRT(value)";
00751     }
00752     
00753     public String getDescription() {
00754        return SharpTools.translation.getProperty("sqrt_desc");
00755        //return "Returns a square root of a number.";
00756     }    
00757 }
00758 
00765 class FunctionLog extends Function {
00766 
00767     public Number evaluate(SharpTableModel table, Node node,
00768                        int row, int col) throws ParserException {
00769 
00770        return new Float(Math.log
00771                       (getSingleParameter(table, node, row, col)));
00772     }
00773 
00774     public String getUsage() {
00775        return "LOG(value)";
00776     }
00777     
00778     public String getDescription() {
00779        return SharpTools.translation.getProperty("log_desc");
00780        //return "Returns the logarithm of a number to the base e.";
00781     }
00782 }
00783 
00790 class FunctionMeandev extends Function {    
00791 
00792     // mean deviation is the average of absolute deviations from the mean value
00793     
00794     public Number evaluate(SharpTableModel table, Node node,
00795                        int row, int col) throws ParserException {
00796 
00797        float dev = 0;
00798        float nCells = (new FunctionCount()).
00799            evaluate(table, node, row, col).floatValue();
00800        float mean = (new FunctionAverage()).
00801            evaluate(table, node, row, col).floatValue();
00802 
00803        LinkedList params = node.getParams();
00804        
00805        if (params != null) {
00806 
00807            Iterator it = params.iterator();
00808 
00809            while (it.hasNext()) {
00810 
00811               Node exp = (Node)it.next();
00812               
00813               if (isRange(exp)) {      
00814                   CellPoint[] addr =
00815                      getFirst(exp).getAddressRange(row, col);
00816                   
00817                   for (int i = addr[0].getRow(); i <= addr[1].getRow(); i++)
00818                      for (int j = addr[0].getCol(); j <= addr[1].getCol(); j++){
00819                          dev += Math.abs(table.getNumericValueAt(i, j).
00820                                        floatValue() - mean);
00821                      }
00822               }
00823               else {
00824                   dev +=
00825                      Math.abs(Formula.evaluate(table, exp.getExp(), row, col).floatValue());
00826               }
00827            }
00828            
00829        }      
00830 
00831        return new Float(dev/nCells);
00832     }
00833 
00834     public String getUsage() {
00835        return "MEANDEV(value1,value2,...)";
00836     }
00837     
00838     public String getDescription() {
00839        return SharpTools.translation.getProperty("meandev_desc");
00840        //return "Returns the average absolute deviation in a set of values.";
00841     }  
00842 }
00843 
00851 class FunctionStddev extends Function {
00852 
00853     public Number evaluate(SharpTableModel table, Node node,
00854                        int row, int col) throws ParserException {
00855 
00856        float dev = 0;
00857        float nCells = (new FunctionCount()).
00858            evaluate(table, node, row, col).floatValue();
00859        float mean = (new FunctionAverage()).
00860            evaluate(table, node, row, col).floatValue();
00861 
00862        LinkedList params = node.getParams();
00863        
00864        if (params != null) {
00865 
00866            Iterator it = params.iterator();
00867 
00868            while (it.hasNext()) {
00869 
00870               Node exp = (Node)it.next();
00871               
00872               if (isRange(exp)) {      
00873                   CellPoint[] addr =
00874                      getFirst(exp).getAddressRange(row, col);
00875                   
00876                   for (int i = addr[0].getRow(); i <= addr[1].getRow(); i++)
00877                      for (int j = addr[0].getCol(); j <= addr[1].getCol(); j++){
00878                          float temp = Math.abs(table.getNumericValueAt(i, j).
00879                                             floatValue() - mean);
00880                          dev += temp*temp;
00881                      }
00882               }
00883               else {
00884                   float temp = Math.abs(Formula.evaluate(table, exp.getExp(), row, col).floatValue());
00885                   dev += temp*temp;
00886 
00887               }
00888            }
00889            
00890        }      
00891 
00892        return new Float(Math.sqrt(dev/(nCells - 1)));
00893     }
00894 
00895     public String getUsage() {
00896        return "STDDEV(value1,value2,...)";
00897     }
00898     
00899     public String getDescription() {
00900        return SharpTools.translation.getProperty("stddev_desc");
00901        //return "Returns the standard deviation in a set of values.";
00902     }
00903 }
00904 
00912 class FunctionPI extends Function {
00913     
00914     public Number evaluate(SharpTableModel table, Node node,
00915                        int row, int col) throws ParserException {
00916 
00917        // no parameters allowed
00918        if (node.getParams().size() != 0)
00919            throw new ParserException("#PARAM?");
00920               
00921        return new Float(Math.PI);
00922     }
00923 
00924     public String getUsage() {
00925        return "PI()";
00926     }
00927     
00928     public String getDescription() {
00929        return SharpTools.translation.getProperty("pi_desc");
00930        //return "Returns the value of PI.";
00931     }
00932 
00933     public boolean requireParams() { return false; }
00934 }
00935 
00943 class FunctionE extends Function {
00944     
00945     public Number evaluate(SharpTableModel table, Node node,
00946                        int row, int col) throws ParserException {
00947 
00948        // no parameters allowed
00949        if (node.getParams().size() != 0)
00950            throw new ParserException("#PARAM?");
00951 
00952        return new Float(Math.E);
00953     }
00954 
00955     public String getUsage() {
00956        return "E()";
00957     }
00958     
00959     public String getDescription() {
00960        return SharpTools.translation.getProperty("e_desc");
00961        //return "Returns value of e.";
00962     }
00963 
00964     public boolean requireParams() { return false; }
00965 }
00966