Configuration ############# .. highlight:: php ``Arokettu\ArithmeticParser\Config`` class is used to configure the calculator and the parser. Config is mutable but it is cloned internally when passed to prevent external alterations. .. warning:: Calling parser and calculator with a different config objects is not supported unless only functions were added. ``Config::default()`` ===================== The default preset used when no config is specified. .. _calc-config-funcs: Functions ========= .. versionadded:: 1.1 removeFunction() and clearFunctions() .. versionchanged:: 2.0 Functions can accept any number of arguments .. versionadded:: 2.0 ``pi()``, ``e()``, ``if()`` .. versionchanged:: 2.0 ``log()`` now also has ``base`` optional param .. versionadded:: 3.0 ``defined()``, precision param for ``round()``, ``true()``, ``false()``, ``nan()``, ``inf()`` .. versionchanged:: 3.0 ``setFunctions()`` and ``addFunctions()`` no longer accept callables, ``addFunctionsFromCallables()`` was added to handle them The function must be a callable that accepts float arguments. Default functions: `abs `__, `exp `__, `log(num, base = e()) `__, `log10 `__, `sqrt `__, `acos `__, `asin `__, `atan `__, `cos `__, `sin `__, `tan `__, `acosh `__, `asinh `__, `atanh `__, `cosh `__, `sinh `__, `tanh `__, `ceil `__, `floor `__, `round(num, precision = 0) `__, `deg2rad `__, `rad2deg `__, `pi `__, `e `__, `true `__, `false `__, `nan `__, `inf `__. Default lazy functions: * ``if(if, then, else)``. Regular ``if`` expression * ``defined(variable)``. Returns 1 if variable is defined and 0 if not .. warning:: Lazy functions act like regular functions in the default calculator. For example, ``if (a = 0, 0, 1/a)`` will result in division by zero if ``a = 0``. You can: * Replace functions with your own list:: setFunctions( new Config\Func('myfunc2', fn (float $a) => $a ** 2) ) * Add new functions:: setFunctions( new Config\Func('myfunc3', fn (float $a) => $a ** 3) ) // or by callable $config->addFunctionsFromCallables(myfunc4: fn (float $a) => $a ** 4); * Remove functions:: removeFunctions('acos', 'asin'); $config->removeFunction('acos'); // semantic alias for removeFunctions('acos') $config->clearFunctions(); // remove all functions Callable must accept all floats for a regular function or all instances of ``LazyArgument`` for a lazy function. Lazy functions can be used with the default calculator, but they will act like regular functions in that case. For example, function that returns its first nonzero argument:: addFunctionFromCallable('first_nonzero', function (LazyArgument ...$args) { foreach ($args as $a) { $value = $a->getValue(); if ($value !== 0.0) { return $value; } } return 0; }, true); var_dump(LazyCalculator::evaluate( 'first_nonzero(a, b, c, notafunc(d) / 0)', $config, a: 0, b: 0, c: 3 )); // 3 Operators ========= .. versionadded:: 1.1 removeOperator() and clearOperators() .. versionadded:: 2.0 ``<``, ``>``, ``<=``, ``>=``, ``=``, ``==``, ``<>``, ``!=``, ``and``, ``AND``, ``or``, ``OR`` .. versionadded:: 3.0 ``not`` (also ``NOT``) Operators can be unary and binary. Operator symbol can be any string without digits. Be wary when using latin character based operators, they are case-sensitive and may shadow variables and functions. Default operators: * ``+``, ``-`` in both unary and binary form. They are built-in and are not configurable. * ``*``, ``/``, ``<``, ``>``, ``<=``, ``>=``, ``=`` (also ``==``), ``<>`` (also ``!=``), ``and`` (also ``AND``), ``or`` (also ``OR``), ``not`` (also ``NOT``). .. note:: ``and/AND`` and ``or/OR``) are lazy like in most programming languages You can: * Replace operators with your own list:: setOperators( new BinaryOperator('×', fn (float $a, float $b) => $a * $b, BinaryOperator::PRIORITY_MUL), new BinaryOperator('÷', fn (float $a, float $b) => $a / $b, BinaryOperator::PRIORITY_MUL), ); * Add new operators:: addOperators( new BinaryOperator('^', pow(...), BinaryOperator::PRIORITY_POW, BinaryAssoc::RIGHT), new UnaryOperator('!', factorial(...), UnaryPos::POSTFIX), ); * Remove operators:: removeOperators('*', '/'); // you cannot divide by zero if you cannot divide $config->removeOperator('/'); // semantic alias for removeOperators('/') // leave only + and - $config->clearOperators(); // + and - are handled specially and can't be removed Like functions, operators can be lazy, in that case callables must accept instances of ``LazyArgument`` as arguments. For example, OR operator that returns the actual value of the first truth-y argument:: addOperator(new Config\BinaryOperator( '||', fn (LazyArgument $a, LazyArgument $b) => $a->getValue() ?: $b->getValue(), BinaryPriority::OR, Config\BinaryAssoc::LEFT, true, )); var_dump(LazyCalculator::evaluate('a || b', $config, a: 0, b: 12)); // 12 var_dump(LazyCalculator::evaluate('a || b / 0', $config, a: 123)); // 123