home *** CD-ROM | disk | FTP | other *** search
/ Enter 2004 June / ENTER.ISO / files / xampp-win32-1.4.5-installer.exe / xampp / RPN.php < prev    next >
Encoding:
PHP Script  |  2004-03-24  |  27.9 KB  |  1,001 lines

  1. <?php
  2.  
  3. /**
  4.  * Math::Rpn
  5.  *
  6.  * Purpose:
  7.  *
  8.  *     Change Expression To RPN (Reverse Polish Notation), Evaluate RPN Expression
  9.  *
  10.  * Example:
  11.  *
  12.  *     $expression = "(2^3)+sin(30)-(!4)+(3/4)";
  13.  *
  14.  *     $rpn = new Math_Rpn();
  15.  *     echo $rpn->calculate($expression,'deg',false);
  16.  *
  17.  *
  18.  * @author   Maciej Szczytowski <admin@e-rower.pl>
  19.  * @version  1.0
  20.  * @package  math
  21.  * @access   public
  22.  */
  23.  
  24. require_once 'PEAR.php';
  25.  
  26. class Math_Rpn
  27. {
  28.     /**
  29.      * Input expression
  30.      *
  31.      * @var    string
  32.      * @access private
  33.      */
  34.     var $_input = '';
  35.  
  36.     /**
  37.      * Array with input expression
  38.      *
  39.      * @var    array
  40.      * @access private
  41.      */
  42.     var $_input_array = array();
  43.  
  44.     /**
  45.      * Array with output expression in RPN
  46.      *
  47.      * @var    array
  48.      * @access private
  49.      */
  50.     var $_output = array();
  51.  
  52.     /**
  53.      * Temporary stack
  54.      *
  55.      * @var    array
  56.      * @access private
  57.      */
  58.     var $_stack = array();
  59.  
  60.     /**
  61.      * Value of expression
  62.      *
  63.      * @var    float
  64.      * @access private
  65.      */
  66.     var $_value = 0.0;
  67.  
  68.     /**
  69.      * Angle's unit: rad - true, deg - false
  70.      *
  71.      * @var    boolean
  72.      * @access private
  73.      */
  74.     var $_angle = true;
  75.  
  76.     /**
  77.      * PEAR Error
  78.      *
  79.      * @var    object PEAR
  80.      * @access private
  81.      */
  82.     var $_error = null;
  83.  
  84.     /**
  85.      * Timer
  86.      *
  87.      * @var    float
  88.      * @access private
  89.      */
  90.     var $_timer = 0.0;
  91.  
  92.     /**
  93.      * Array of operators whit priority and math function
  94.      * operator => (name, priority, number of arguments, function)
  95.      *
  96.      * @var    array
  97.      * @access private
  98.      */
  99.     var $_operation = array (
  100.         '('    => array ('left bracket', 0),
  101.         ')'    => array ('right bracket', 1),
  102.         '+'    => array ('sum', 1, 2, '_sum'),
  103.         '-'    => array ('difference', 1, 2, '_difference'),
  104.         '*'    => array ('multiplication', 2, 2, '_multiplication'),
  105.         '/'    => array ('division', 2, 2, '_division'),
  106.         'r'    => array ('root', 3, 2, '_root'),
  107.         '^'    => array ('power', 3, 2, '_power'),
  108.         'sin'  => array ('sine', 3, 1, '_sin'),
  109.         'cos'  => array ('cosine', 3, 1, '_cos'),
  110.         'tan'  => array ('tangent', 3, 1, '_tan'),
  111.         'asin' => array ('asine', 3, 1, '_asin'),
  112.         'acos' => array ('acosine', 3, 1, '_acos'),
  113.         'atan' => array ('atangent', 3, 1, '_atan'),
  114.         'sqrt' => array ('square root', 3, 1, '_sqrt'),
  115.         'exp'    => array ('power of e', 3, 1, '_exp'),
  116.         'log'  => array ('logarithm', 3, 1, '_log'),
  117.         'ln'   => array ('natural logarithm', 3, 1, '_ln'),
  118.         'E'  => array ('power of 10', 3, 1, '_E'),
  119.         'abs'  => array ('absolute value', 3, 1, '_abs'),
  120.         '!'    => array ('factorial', 3, 1, '_factorial'),
  121.         'pi'   => array ('value of pi', 3, 0, '_const_pi'),
  122.         'e'    => array ('value of e', 3, 0, '_const_e'),
  123.         'mod'    => array ('modulo', 3, 2, '_mod'),
  124.         'div'    => array ('integer division', 3, 2, '_div'),
  125.     );
  126.  
  127.     /**
  128.      * Return a PEAR error
  129.      *
  130.      * @return object PEAR error
  131.      * @access private
  132.      */
  133.     function _raiseError ($error) {
  134.         return PEAR::raiseError($error);
  135.     }
  136.  
  137.     /**
  138.      * Return a operator's array
  139.      *
  140.      * @return array Array with operator's name, priority, arguments, function's name and syntax
  141.      * @access public
  142.      */
  143.     function getOperators () {
  144.         $return = array();
  145.         while(list($key, $val) = each($this->_operation)) {
  146.  
  147.             if (array_key_exists (2, $val) && $val[2] == 2) {
  148.                 $syntax = 'A ' . $key . ' B';
  149.                 $arguments = 2;
  150.             } elseif (array_key_exists (2, $val) && $val[2] == 1) {
  151.                 $syntax = $key . ' A';
  152.                 $arguments = 1;
  153.             } else {
  154.                 $syntax = $key;
  155.                 $arguments = 0;
  156.             }
  157.  
  158.             if(array_key_exists (3, $val)) $function = $val[3]; else $function = '';
  159.  
  160.             $return[] = array (
  161.                 'operator' => $key,
  162.                 'name' => $val[0],
  163.                 'priority' => $val[1],
  164.                 'arguments' => $arguments,
  165.                 'function' => $function,
  166.                 'syntax' => $syntax
  167.             );
  168.         }
  169.  
  170.         return $return;
  171.     }
  172.  
  173.     /**
  174.      * Add new operator
  175.      *
  176.      * @param string $operator New operator
  177.      * @param string $function Function name
  178.      * @param integer $priority New operator's priority
  179.      * @param integer $no_of_arg Number of function's arguments
  180.      * @param string $text New operator's description
  181.      * @access public
  182.      */
  183.     function addOperator ($operator, $function_name, $priority = 3, $no_of_arg = 0, $text = '') {
  184.         if(preg_match("/^([\W\w]+)\:\:([\W\w]+)$/",$function_name,$match)) {
  185.             $class = $match[1];
  186.             $method = $match[2];
  187.             $function = array (
  188.                'type' => 'userMethod',
  189.                'class' => $class,
  190.                'method' => $method
  191.             );
  192.         } else {
  193.             $function = array (
  194.                'type' => 'userFunction',
  195.                'function' => $function_name
  196.             );
  197.         }
  198.  
  199.         $this->_operation[$operator] = array ($text, $priority, $no_of_arg, $function);
  200.     }
  201.  
  202.     /**
  203.      * Calculate the $input expression
  204.      *
  205.      * @param mixed $input Infix expression string or RPN expression string
  206.      * @param string $angle Angle's unit - 'rad' or 'deg'
  207.      * @param boolean $is_rpn True if $input is RPN expression or false if $input is infix expression
  208.      * @return mixed Value of $input expression or a PEAR error
  209.      * @access public
  210.      */
  211.     function calculate($input = '', $angle = 'rad', $is_rpn = true) {
  212.  
  213.         $this->_angle = (boolean) ($angle == 'rad');
  214.  
  215.         if($input == '') {
  216.             $this->_error = $this->_raiseError('Empty input expression');
  217.             return $this->_error;
  218.         }
  219.  
  220.         if(!$is_rpn) {
  221.             $this->_input = $input;
  222.  
  223.             $this->_stringToArray ();
  224.             if($this->_error <> null) return $this->_error;
  225.  
  226.             $this->_arrayToRpn();
  227.             if($this->_error <> null) return $this->_error;
  228.         } else {
  229.             if (is_array($input)) {
  230.                 $input = implode(' ', $input);
  231.             }
  232.  
  233.             $this->_input = $input;
  234.             $this->_input_array = explode(' ',$input);
  235.             $this->_output = explode(' ',$input);
  236.         }
  237.  
  238.         $this->_rpnToValue();
  239.         if($this->_error <> null) return $this->_error;
  240.  
  241.         return $this->_value;
  242.     }
  243.  
  244.     /**
  245.      * Calculate the $input expression (alias of calculate())
  246.      *
  247.      * @param mixed $input Infix expression string or RPN expression array
  248.      * @param string $angle Angle's unit - 'rad' or 'deg'
  249.      * @param boolean $is_rpn True if $input is RPN expression or false if $input is infix expression
  250.      * @return mixed Value of $input expression or a PEAR error
  251.      * @access public
  252.      */
  253.     function evaluate($input = '', $angle = 'rad', $is_rpn = false) {
  254.         return $this-> calculate($input, $angle, $is_rpn);
  255.     }
  256.  
  257.     /**
  258.      * Return a input array
  259.      *
  260.      * @return array Input array
  261.      * @access public
  262.      */
  263.     function getInputArray() {
  264.         return $this->_input_array;
  265.     }
  266.  
  267.     /**
  268.      * Return a RPN array
  269.      *
  270.      * @return array RPN array
  271.      * @access public
  272.      */
  273.     function getRpnArray() {
  274.         return $this->_output;
  275.     }
  276.  
  277.     /**
  278.      * Return a counting time in second
  279.      *
  280.      * @return float Counting time in seconds
  281.      * @access public
  282.      */
  283.     function getTimer() {
  284.         return $this->_timer;
  285.     }
  286.  
  287.     /**
  288.      * Check that $key is a key of $array (conformity to php<4.1.0)
  289.      *
  290.      * @param string $key
  291.      * @param array $array
  292.      * @param integer $type 0 - return true if $key is $array's key, 1 - return true if $key is $array's key and there isn't any occurrence of $key in another $array's key
  293.      * @return boolean true when $key is a key of $array, or false
  294.      * @access private
  295.      */
  296.  
  297.     function _keyExists($key,$array,$type) {
  298.         $keys = array_keys($array);
  299.  
  300.         if($type == 1) {
  301.             $count = 0;
  302.             while (list($keys_key, $keys_val) = each($keys)) {
  303.                 if(is_integer(strpos($keys_val, $key)) && (strpos($keys_val, $key)==0)) $count++;
  304.             }
  305.             if(($count==1) && in_array($key,$keys)) return true;
  306.             else return false;
  307.         } else {
  308.             if(in_array($key,$keys)) return true;
  309.             else return false;
  310.         }
  311.     }
  312.  
  313.     /**
  314.      * Check that $value is nan (conformity to php<4.2.0)
  315.      *
  316.      * @param float $value checking value
  317.      * @return boolean true when $value is nan, or false
  318.      * @access private
  319.      */
  320.     function _isNan($value) {
  321.         if(function_exists('is_nan')) {
  322.             return is_nan($value);
  323.         } else {
  324.             if((substr($value,-3) == 'IND') || (substr($value,-3) == 'NAN')) return true;
  325.             else return false;
  326.         }
  327.     }
  328.  
  329.     /**
  330.      * Check that $value is infinite (conformity to php<4.2.0)
  331.      *
  332.      * @param float $value checking value
  333.      * @return boolean true when $value is infinite, or false
  334.      * @access private
  335.      */
  336.     function _isInfinite($value) {
  337.         if(function_exists('is_finite')) {
  338.             return !is_finite($value);
  339.         } else {
  340.             if(substr($value,-3) == 'INF') return true;
  341.             else return false;
  342.         }
  343.     }
  344.  
  345.     /**
  346.      * Change input expression into array
  347.      *
  348.      * @return array Input expression changed into array
  349.      * @access private
  350.      */
  351.     function _stringToArray () {
  352.         $temp_operator = null;
  353.         $temp_value = null;
  354.  
  355.         for($i = 0; $i < strlen($this->_input); $i++) {
  356.             if ($this->_input[$i] == ' ') {
  357.                 if ($temp_operator != null) {
  358.                     array_push($this->_input_array, $temp_operator);
  359.                     $temp_operator = null;
  360.                 }
  361.                 if ($temp_value != null) {
  362.                     array_push($this->_input_array, $temp_value);
  363.                     $temp_value = null;
  364.                 }
  365.             } elseif (($temp_value == null) && (!array_key_exists($temp_operator,$this->_operation) || !array_key_exists(2,$this->_operation[$temp_operator]) || $this->_operation[$temp_operator][2]>0) && ($this->_input[$i] == '-')) {
  366.                 if ($temp_operator != null) {
  367.                     array_push($this->_input_array, $temp_operator);
  368.                     $temp_operator = null;
  369.                 }
  370.  
  371.                 array_push($this->_input_array, '-1');
  372.                 array_push($this->_input_array, '*');
  373.             } elseif ((is_numeric($this->_input[$i])) || ($this->_input[$i] == '.')) {
  374.                 if ($temp_operator != null) {
  375.                     array_push($this->_input_array, $temp_operator);
  376.                     $temp_operator = null;
  377.                 }
  378.  
  379.                 $temp_value .= $this->_input[$i];
  380.             } else {
  381.                 if ($this->_keyExists($temp_operator, $this->_operation, 1)) {
  382.                     array_push($this->_input_array, $temp_operator);
  383.                     $temp_operator = null;
  384.                 }
  385.  
  386.                 if ($temp_value != null) {
  387.                     array_push($this->_input_array, $temp_value);
  388.                     $temp_value = null;
  389.                 }
  390.  
  391.                 $temp_operator .= $this->_input[$i];
  392.             }
  393.         }
  394.  
  395.         if ($temp_operator != null && $temp_operator != ' ') {
  396.             array_push($this->_input_array, $temp_operator);
  397.         } elseif($temp_value != null && $temp_value != ' ') {
  398.             array_push($this->_input_array, $temp_value);
  399.         }
  400.  
  401.         $this->_testInput();
  402.  
  403.         return $this->_input_array;
  404.     }
  405.  
  406.     /**
  407.      * Check input array and return correct array or a PEAR Error
  408.      *
  409.      * @return object Null or a PEAR Error
  410.      * @access private
  411.      */
  412.     function _testInput() {
  413.         if (!count($this->_input_array)) {
  414.             $this->_input_array = null;
  415.             $this->_error = $this->_raiseError('Undefined input array');
  416.             return $this->_error;
  417.         }
  418.  
  419.         $bracket = 0;
  420.         for($i = 0; $i < count($this->_input_array); $i++) if ($this->_input_array[$i] == '(') $bracket++;
  421.         for($i = 0; $i < count($this->_input_array); $i++) if ($this->_input_array[$i] == ')') $bracket--;
  422.  
  423.         if ($bracket <> 0) {
  424.                 $this->_input_array = null;
  425.                 $this->_error = $this->_raiseError('Syntax error');
  426.                 return $this->_error;
  427.         }
  428.  
  429.         for($i = 0; $i < count($this->_input_array); $i++) {
  430.             if ((!is_numeric($this->_input_array[$i])) && (!$this->_keyExists($this->_input_array[$i], $this->_operation, 0))) {
  431.                 $error_operator = $this->_input_array[$i];
  432.                 $this->_input_array = null;
  433.                 $this->_error = $this->_raiseError('Undefined operator \''. $error_operator.'\'');
  434.                 return $this->_error;
  435.             }
  436.         }
  437.  
  438.         $this->_error = null;
  439.         return $this->_error;
  440.     }
  441.  
  442.     /**
  443.      * Add value to the end of stack
  444.      *
  445.      * @param string $value Value to add into stack
  446.      * @access private
  447.      */
  448.     function _stackAdd($value) {
  449.         array_push($this->_stack, $value);
  450.     }
  451.  
  452.     /**
  453.      * Delete and return value from the end of stack
  454.      *
  455.      * @return string Value deleted from stack
  456.      * @access private
  457.      */
  458.     function _stackDelete() {
  459.         return array_pop($this->_stack);
  460.     }
  461.  
  462.     /**
  463.      * Return priority of value
  464.      *
  465.      * @param string $value Value to get priority
  466.      * @return integer Priority
  467.      * @access private
  468.      */
  469.     function _priority($value) {
  470.         return $this->_operation[$value][1];
  471.     }
  472.     /**
  473.      * Return priority of value from the end of stack
  474.      *
  475.      * @return integer Priority of operator from stack's top
  476.      * @access private
  477.      */
  478.     function _stackPriority() {
  479.         $value = $this->_stackDelete();
  480.         $this->_stackAdd($value);
  481.         return $this->_priority($value);
  482.     }
  483.  
  484.     /**
  485.      * Return true whene the stack is empty
  486.      *
  487.      * @return boolean Stack is empty (true) or not (false)
  488.      * @access private
  489.      */
  490.     function _stackEmpty() {
  491.         if (count($this->_stack)) {
  492.             return false;
  493.         }
  494.         else return true;
  495.     }
  496.  
  497.     /**
  498.      * Add value into output array
  499.      *
  500.      * @param string $value Value to add into output array
  501.      * @access private
  502.      */
  503.     function _outputAdd($value) {
  504.         if ($value<>'(') {
  505.             array_push($this->_output, $value);
  506.         }
  507.     }
  508.  
  509.     /**
  510.      * Change input array into RPN array
  511.      *
  512.      * @return array Array with RPN expression
  513.      * @access private
  514.      */
  515.     function _arrayToRpn() {
  516.  
  517.         if ($this->_error <> null) {
  518.             $this->_output = array();
  519.             return $this->_output;
  520.         }
  521.  
  522.         for($i = 0; $i < count($this->_input_array); $i++) {
  523.  
  524.             $temp = $this->_input_array[$i];
  525.  
  526.             if (is_numeric($temp)) {
  527.                 $this->_outputAdd($temp);
  528.             } else {
  529.                 if ($temp == ')') {
  530.                     while(!$this->_stackEmpty() && ($this->_stackPriority() >= 1)) {
  531.                         $this->_outputAdd($this->_stackDelete());
  532.                     }
  533.                     if (!$this->_stackEmpty()) {
  534.                         $this->_stackDelete();
  535.                     }
  536.  
  537.                 } elseif ($temp=='(') {
  538.                     $this->_stackAdd($temp);
  539.                 } elseif (($this->_stackEmpty()) || (($this->_priority($temp) > $this->_stackPriority()))) {
  540.                    $this-> _stackAdd($temp);
  541.                 } else {
  542.                     while(!$this->_stackEmpty() && ($this->_priority($temp) <= $this->_stackPriority())) {
  543.                         $this->_outputAdd($this->_stackDelete());
  544.                     }
  545.                     $this->_stackAdd($temp);
  546.                 }
  547.  
  548.             }
  549.  
  550.         }
  551.  
  552.         while(!$this->_stackEmpty()) {
  553.             $this->_outputAdd($this->_stackDelete());
  554.         }
  555.  
  556.         return $this->_output;
  557.     }
  558.  
  559.     /**
  560.      * Return position of the first operator in array
  561.      *
  562.      * @param array $array Temporary array
  563.      * @return integer Position of the first operator
  564.      * @access private
  565.      */
  566.     function _nextOperator($array) {
  567.         $pos = 0;
  568.         while(is_numeric($array[$pos])) {
  569.             $pos++;
  570.             if ($pos >= count($array)) {
  571.                 return -1;
  572.             }
  573.         }
  574.         return $pos;
  575.  
  576.     }
  577.  
  578.     /**
  579.      * Delete from array operator [posision $pos] and its argument and insert new value
  580.      *
  581.      * @param array $temp Temporary array
  582.      * @param integer $pos Position of the last operator
  583.      * @param integer $arg Number of last operator's arguments
  584.      * @param float $result Last operation result
  585.      * @return array New temporary array
  586.      * @access private
  587.      */
  588.     function _refresh($temp, $pos, $arg, $result) {
  589.         $temp1 = array_slice($temp, 0, $pos-$arg);
  590.         $temp1[] = $result;
  591.         $temp2 = array_slice($temp, $pos+1);
  592.         return array_merge($temp1, $temp2);
  593.     }
  594.  
  595.     /**
  596.      * Math function
  597.      *
  598.      * @param array $temp Temporary array
  599.      * @param integer $pos Position of operator
  600.      * @return float Function's relult
  601.      * @access private
  602.      */
  603.     function _sum($temp, $pos) {
  604.         return $temp[$pos-2]+$temp[$pos-1];
  605.     }
  606.  
  607.     /**
  608.      * Math function
  609.      *
  610.      * @param array $temp Temporary array
  611.      * @param integer $pos Position of operator
  612.      * @return float Function's relult
  613.      * @access private
  614.      */
  615.     function _difference($temp, $pos) {
  616.         return $temp[$pos-2]-$temp[$pos-1];
  617.     }
  618.  
  619.     /**
  620.      * Math function
  621.      *
  622.      * @param array $temp Temporary array
  623.      * @param integer $pos Position of operator
  624.      * @return float Function's relult
  625.      * @access private
  626.      */
  627.     function _multiplication($temp, $pos) {
  628.         return $temp[$pos-2]*$temp[$pos-1];
  629.     }
  630.  
  631.     /**
  632.      * Math function
  633.      *
  634.      * @param array $temp Temporary array
  635.      * @param integer $pos Position of operator
  636.      * @return float Function's relult
  637.      * @access private
  638.      */
  639.     function _division($temp, $pos) {
  640.         if ($temp[$pos-1]==0) {
  641.             $this->_error = $this->_raiseError('Division by 0');
  642.             $this->_value = null;
  643.             return $this->_value;
  644.         }
  645.         return $temp[$pos-2]/$temp[$pos-1];
  646.     }
  647.  
  648.     /**
  649.      * Math function
  650.      *
  651.      * @param array $temp Temporary array
  652.      * @param integer $pos Position of operator
  653.      * @return float Function's relult
  654.      * @access private
  655.      */
  656.     function _root($temp, $pos) {
  657.         return pow($temp[$pos-1], (1/$temp[$pos-2]));
  658.     }
  659.  
  660.     /**
  661.      * Math function
  662.      *
  663.      * @param array $temp Temporary array
  664.      * @param integer $pos Position of operator
  665.      * @return float Function's relult
  666.      * @access private
  667.      */
  668.     function _power($temp, $pos) {
  669.         return pow($temp[$pos-2], $temp[$pos-1]);
  670.     }
  671.  
  672.     /**
  673.      * Math function
  674.      *
  675.      * @param array $temp Temporary array
  676.      * @param integer $pos Position of operator
  677.      * @return float Function's relult
  678.      * @access private
  679.      */
  680.     function _sin($temp, $pos) {
  681.         if ($this->_angle) {
  682.             $angle = $temp[$pos-1];
  683.         } else {
  684.             $angle = deg2rad($temp[$pos-1]);
  685.         }
  686.         return sin($angle);
  687.     }
  688.  
  689.     /**
  690.      * Math function
  691.      *
  692.      * @param array $temp Temporary array
  693.      * @param integer $pos Position of operator
  694.      * @return float Function's relult
  695.      * @access private
  696.      */
  697.     function _cos($temp, $pos) {
  698.         if ($this->_angle) {
  699.             $angle = $temp[$pos-1];
  700.         } else {
  701.             $angle = deg2rad($temp[$pos-1]);
  702.         }
  703.         return cos($angle);
  704.     }
  705.  
  706.     /**
  707.      * Math function
  708.      *
  709.      * @param array $temp Temporary array
  710.      * @param integer $pos Position of operator
  711.      * @return float Function's relult
  712.      * @access private
  713.      */
  714.     function _tan($temp, $pos) {
  715.         if ($this->_angle) {
  716.             $angle = $temp[$pos-1];
  717.         } else {
  718.             $angle = deg2rad($temp[$pos-1]);
  719.         }
  720.         return tan($angle);
  721.     }
  722.  
  723.     /**
  724.      * Math function
  725.      *
  726.      * @param array $temp Temporary array
  727.      * @param integer $pos Position of operator
  728.      * @return float Function's relult
  729.      * @access private
  730.      */
  731.     function _asin($temp, $pos) {
  732.         $angle = asin($temp[$pos-1]);
  733.         if (!$this->_angle) {
  734.             $angle = rad2deg($angle);
  735.         }
  736.         return $angle;
  737.     }
  738.  
  739.     /**
  740.      * Math function
  741.      *
  742.      * @param array $temp Temporary array
  743.      * @param integer $pos Position of operator
  744.      * @return float Function's relult
  745.      * @access private
  746.      */
  747.     function _acos($temp, $pos) {
  748.         $angle = acos($temp[$pos-1]);
  749.         if (!$this->_angle) {
  750.             $angle = rad2deg($angle);
  751.         }
  752.         return $angle;
  753.     }
  754.  
  755.     /**
  756.      * Math function
  757.      *
  758.      * @param array $temp Temporary array
  759.      * @param integer $pos Position of operator
  760.      * @return float Function's relult
  761.      * @access private
  762.      */
  763.     function _atan($temp, $pos) {
  764.         $angle = atan($temp[$pos-1]);
  765.         if (!$this->_angle) {
  766.             $angle = rad2deg($angle);
  767.         }
  768.         return $angle;
  769.     }
  770.  
  771.     /**
  772.      * Math function
  773.      *
  774.      * @param array $temp Temporary array
  775.      * @param integer $pos Position of operator
  776.      * @return float Function's relult
  777.      * @access private
  778.      */
  779.     function _sqrt($temp, $pos) {
  780.         return sqrt($temp[$pos-1]);
  781.     }
  782.  
  783.     /**
  784.      * Math function
  785.      *
  786.      * @param array $temp Temporary array
  787.      * @param integer $pos Position of operator
  788.      * @return float Function's relult
  789.      * @access private
  790.      */
  791.     function _exp($temp, $pos) {
  792.         return exp($temp[$pos-1]);
  793.     }
  794.  
  795.     /**
  796.      * Math function
  797.      *
  798.      * @param array $temp Temporary array
  799.      * @param integer $pos Position of operator
  800.      * @return float Function's relult
  801.      * @access private
  802.      */
  803.     function _log($temp, $pos) {
  804.         return log10($temp[$pos-1]);
  805.     }
  806.  
  807.     /**
  808.      * Math function
  809.      *
  810.      * @param array $temp Temporary array
  811.      * @param integer $pos Position of operator
  812.      * @return float Function's relult
  813.      * @access private
  814.      */
  815.     function _ln($temp, $pos) {
  816.         return log($temp[$pos-1]);
  817.     }
  818.  
  819.     /**
  820.      * Math function
  821.      *
  822.      * @param array $temp Temporary array
  823.      * @param integer $pos Position of operator
  824.      * @return float Function's relult
  825.      * @access private
  826.      */
  827.     function _const_pi($temp, $pos) {
  828.         return M_PI;
  829.     }
  830.  
  831.     /**
  832.      * Math function
  833.      *
  834.      * @param array $temp Temporary array
  835.      * @param integer $pos Position of operator
  836.      * @return float Function's relult
  837.      * @access private
  838.      */
  839.     function _const_e($temp, $pos) {
  840.         return M_E;
  841.     }
  842.  
  843.     /**
  844.      * Math function
  845.      *
  846.      * @param array $temp Temporary array
  847.      * @param integer $pos Position of operator
  848.      * @return float Function's relult
  849.      * @access private
  850.      */
  851.     function _E($temp, $pos) {
  852.         return pow(10, $temp[$pos-1]);
  853.     }
  854.  
  855.     /**
  856.      * Math function
  857.      *
  858.      * @param array $temp Temporary array
  859.      * @param integer $pos Position of operator
  860.      * @return float Function's relult
  861.      * @access private
  862.      */
  863.     function _factorial($temp, $pos) {
  864.         $factorial = 1;
  865.         for($i=1;$i<=$temp[$pos-1];$i++) {
  866.             $factorial *= $i;
  867.         }
  868.         return $factorial;
  869.     }
  870.  
  871.     /**
  872.      * Math function
  873.      *
  874.      * @param array $temp Temporary array
  875.      * @param integer $pos Position of operator
  876.      * @return float Function's relult
  877.      * @access private
  878.      */
  879.     function _abs($temp, $pos) {
  880.         return abs($temp[$pos-1]);
  881.     }
  882.  
  883.     /**
  884.      * Math function
  885.      *
  886.      * @param array $temp Temporary array
  887.      * @param integer $pos Position of operator
  888.      * @return float Function's relult
  889.      * @access private
  890.      */
  891.     function _mod($temp, $pos) {
  892.         return $temp[$pos-2]%$temp[$pos-1];
  893.     }
  894.  
  895.     /**
  896.      * Math function
  897.      *
  898.      * @param array $temp Temporary array
  899.      * @param integer $pos Position of operator
  900.      * @return float Function's relult
  901.      * @access private
  902.      */
  903.     function _div($temp, $pos) {
  904.         return floor($temp[$pos-2]/$temp[$pos-1]);
  905.     }
  906.  
  907.     /**
  908.      * Calculate RPN Expression and return value
  909.      *
  910.      * @return float Result of input expression
  911.      * @access private
  912.      */
  913.     function _rpnToValue() {
  914.  
  915.         $time1 = $this->_getMicroTime();
  916.  
  917.         if ($this->_error <> null) {
  918.             $this->_value = null;
  919.             return $this->_value;
  920.         }
  921.  
  922.         $this->_value = 0;
  923.         $temp = $this->_output;
  924.  
  925.         do {
  926.             $pos = $this->_nextOperator($temp);
  927.  
  928.             if ($pos == -1) {
  929.                 $this->_error = $this->_raiseError('Syntax error');
  930.                 $this->_value = null;
  931.                 return $this->_value;
  932.             }
  933.  
  934.             $operator = $this->_operation[$temp[$pos]];
  935.             $arg = $operator[2];
  936.             $function = $operator[3];
  937.  
  938.             if (($arg==2) && ((!is_numeric($temp[$pos-1])) || (!is_numeric($temp[$pos-2])))) {
  939.                 $this->_error = $this->_raiseError('Syntax error');
  940.                 $this->_value = null;
  941.                 return $this->_value;
  942.             } elseif (($arg==1) && (!is_numeric($temp[$pos-1]))) {
  943.                 $this->_error = $this->_raiseError('Syntax error');
  944.                 $this->_value = null;
  945.                 return $this->_value;
  946.             }
  947.  
  948.             if(is_array($function)) {
  949.  
  950.                 if($arg==2) $arg_array = array($temp[$pos-2],$temp[$pos-1]);
  951.                 elseif($arg==1) $arg_array = array($temp[$pos-1]);
  952.                 else $arg_array = array();
  953.  
  954.                 if($function['type'] == 'userFunction') {
  955.                     $this->_value = call_user_func_array($function['function'], $arg_array);
  956.                 } else {
  957.                     $function_array = array(&$function['class'], $function['method']);
  958.                     $this->_value = call_user_func_array($function_array, $arg_array);
  959.                 }
  960.             } else {
  961.                 $this->_value = $this->$function($temp, $pos);
  962.             }
  963.  
  964.             if ($this->_isNan($this->_value)) {
  965.                 $this->_error = $this->_raiseError('NAN value');
  966.                 $this->_value = null;
  967.                 return $this->_value;
  968.             } elseif ($this->_isInfinite($this->_value)) {
  969.                 $this->_error = $this->_raiseError('Infinite value');
  970.                 $this->_value = null;
  971.                 return $this->_value;
  972.             } elseif (is_null($this->_value)) {
  973.                 return $this->_value;
  974.             }
  975.  
  976.             $temp = $this->_refresh($temp, $pos, $arg, $this->_value);
  977.         } while(count($temp) > 1);
  978.  
  979.         $this->_value = $temp[0];
  980.  
  981.         $time2 = $this->_getMicroTime();
  982.  
  983.         $this->_timer = $time2 - $time1;
  984.  
  985.         return $this->_value;
  986.     }
  987.  
  988.     /**
  989.      * Return a time in second
  990.      *
  991.      * @return float Current time in seconds
  992.      * @access private
  993.      */
  994.     function _getMicroTime() {
  995.         list($usec, $sec) = explode(" ", microtime());
  996.         return ((float)$usec + (float)$sec);
  997.     }
  998.  
  999. }
  1000.  
  1001. ?>