PageRenderTime 53ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/php/Math/RPN.php

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