From 0a4028e9f1170bda49fe6bc10b9b1be04441d8b2 Mon Sep 17 00:00:00 2001 From: John Denker Date: Thu, 11 Nov 2021 16:02:59 -0700 Subject: implement floor(x), ceil(x), and modulo (x % y) --- parser.php | 122 ++++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 92 insertions(+), 30 deletions(-) (limited to 'parser.php') diff --git a/parser.php b/parser.php index 80e01c2..cd7e6c2 100644 --- a/parser.php +++ b/parser.php @@ -858,6 +858,61 @@ class qtype_algebra_parser_divide extends qtype_algebra_parser_term { ); } +/** + * Class representing a modulo operation in an algebraic expression. + * + * The parser creates an instance of this term when it finds a string matching the modulo + * operator's syntax. The string which corresponds to the term is passed to the constructor + * of this subclass. + */ +class qtype_algebra_parser_modulo extends qtype_algebra_parser_term { + + /** + * Constructs an instance of a modulo operator term. + * + * This function initializes an instance of a modulo operator term using the string which + * matches the modulo operator expression. Since this is simply the character representing + * the operator it is not used except when producing a string representation of the term. + * + * @param $text string matching the term's regular expression + */ + public function __construct($text) { + parent::__construct(self::NARGS, self::$formats, $text); + } + + /** + * Evaluates the modulo operation numerically. + * + * Overrides the base class method to simply return the numerical value of the modulo + * operation. The method evaluates the two arguments of the term and then performs + * the required operation to get the return value. + * + * @param $params array of values keyed by variable name + * @return the numerical value of the term given the provided values for the variables + */ + public function evaluate($params) { + $this->check_arguments(); + // Get the value we are trying to modulo by. + $denom = $this->_arguments[1]->evaluate($params); + // Check to see if this is zero. + if ($denom == 0) { + // Check the sign of the other argument and use to determine whether we return + // plus or minus infinity. + return INF * $this->_arguments[0]->evaluate($params); + } else { + $nume = $this->_arguments[0]->evaluate($params); + $rslt = fmod($nume, $denom); + return $rslt; + } + } + + // Static class properties. + const NARGS = 2; + private static $formats = array( + 'str' => '%s%%%s', + 'tex' => '{%s}\%%{%s}' + ); +} /** * Class representing a multiplication operation in an algebraic expression. @@ -1307,16 +1362,19 @@ class qtype_algebra_parser_function extends qtype_algebra_parser_term { * functions are implemented without pseudonyms */ public static $fnmap = array (); - public static $texmap = array('sqrt' => '\\sqrt', - 'log2' => '\\log_{2}', - 'log10' => '\\log_{10}', - 'asin' => '\\sin^{-1}', - 'acos' => '\\cos^{-1}', - 'atan' => '\\tan^{-1}', - 'asinh' => '\\sinh^{-1}', - 'acosh' => '\\cosh^{-1}', - 'atanh' => '\\tanh^{-1}', - ); + public static $texmap = array( + 'floor' => '\\mathrm{floor}', + 'ceil' => '\\mathrm{ceil}', + 'sqrt' => '\\sqrt', + 'log2' => '\\log_{2}', + 'log10' => '\\log_{10}', + 'asin' => '\\sin^{-1}', + 'acos' => '\\cos^{-1}', + 'atan' => '\\tan^{-1}', + 'asinh' => '\\sinh^{-1}', + 'acosh' => '\\cosh^{-1}', + 'atanh' => '\\tanh^{-1}', + ); // List of functions requiring special brackets. public static $bracketmap = array ('sqrt' @@ -1441,32 +1499,35 @@ class qtype_algebra_parser { // Functions which the parser will understand. // You have to implement any that are not standard PHP math functions. - public static $functions = array ('sqrt', - 'exp', - 'log2', - 'ln', - 'log', - 'log10', - 'sinh', - 'cosh', - 'tanh', - 'sin', - 'cos', - 'tan', - 'asin', - 'acos', - 'atan', - 'asinh', - 'acosh', - 'atanh', - ); + public static $functions = array ( + 'floor', + 'ceil', + 'sqrt', + 'exp', + 'log2', + 'ln', + 'log', + 'log10', + 'sinh', + 'cosh', + 'tanh', + 'sin', + 'cos', + 'tan', + 'asin', + 'acos', + 'atan', + 'asinh', + 'acosh', + 'atanh', + ); // Array to define the priority of the different operations. The parser implements the standard BODMAS priority: // brackets, order (power), division, mulitplication, addition, subtraction. private static $priority = array ( array('qtype_algebra_parser_power'), array('qtype_algebra_parser_function'), - array('qtype_algebra_parser_divide', 'qtype_algebra_parser_multiply'), + array('qtype_algebra_parser_divide', 'qtype_algebra_parser_multiply', 'qtype_algebra_parser_modulo'), array('qtype_algebra_parser_add', 'qtype_algebra_parser_subtract') ); @@ -1493,6 +1554,7 @@ class qtype_algebra_parser { $this->_tokens = array ( array ('/(\^|\*\*)/A', 'qtype_algebra_parser_power' ) , array ('/\//A', 'qtype_algebra_parser_divide' ) + , array ('/%/A', 'qtype_algebra_parser_modulo' ) , array ('/\*/A', 'qtype_algebra_parser_multiply' ) , array ('/\+/A', 'qtype_algebra_parser_add' ) , array ('/-/A', 'qtype_algebra_parser_subtract' ) -- cgit v1.2.3