<!-- Module User's Guide -->

<chapter>
	
	<title>&adminguide;</title>

	<section id="overview" xreflabel="Overview">
	<title>Overview</title>
	<para>
		The mathops module provides a series of functions which enable various
		floating point operations at &osips; script level.
	</para>
	</section>

	<section id="dependencies" xreflabel="Dependencies">
	<title>Dependencies</title>
	<section>
		<title>&osips; Modules</title>
		<para>
		The following modules must be loaded before this module:
			<itemizedlist>
			<listitem>
			<para>
				<emphasis>No dependencies on other &osips; modules.</emphasis>.
			</para>
			</listitem>
			</itemizedlist>
		</para>
	</section>

	<section>
		<title>External Libraries or Applications</title>
		<para>
		The following libraries or applications must be installed before 
		running &osips; with this module loaded:
			<itemizedlist>
			<listitem>
			<para>
				<emphasis>None</emphasis>.
			</para>
			</listitem>
			</itemizedlist>
		</para>
	</section>
	</section>

	<section id="exported_parameters" xreflabel="Exported Parameters">
	<title>Exported Parameters</title>
	<section id="param_decimal_digits" xreflabel="decimal_digits">
		<title><varname>decimal_digits</varname> (integer)</title>
		<para>
		The precision of the results returned by all the module functions.
		The higher the <quote>decimal_digits</quote> value, the more decimal
		digits the results will have.
		</para>
		<para>
		Default value is <quote>6</quote>.
		</para>
		<example>
		<title>Setting the decimal_digits module parameter</title>
		<programlisting format="linespecific">
modparam("mathops", "decimal_digits", 10)
</programlisting>
		</example>
	</section>
	</section>

	<section id="exported_functions" xreflabel="exported_functions">
	<title>Exported Functions</title>
	<section id="func_math_eval" xreflabel="math_eval()">
		<title>
		<function moreinfo="none">math_eval(expression, result_var)</function>
		</title>
		<para>
		The function evaluates a given expression and writes the result in the
		output pseudo-variable. Evaluation uses tinyexpr (see https://github.com/codeplea/tinyexpr).
		</para>
		<para>
		Currently allowed syntax for specifying an expression:
		<itemizedlist>
		<listitem>
			<para> Nested parentheses </para>
		</listitem>
		<listitem>
			<para> addition (+), subtraction/negation (-), multiplication (*), division (/), exponentiation (^) and modulus (%) with the normal operator precedence (the one exception being that exponentiation is evaluated left-to-right) </para>
		</listitem>
                <listitem>
			<para> C math functions: abs (calls to fabs), acos, asin, atan, ceil, cos, cosh, exp, floor, ln (calls to log), log (calls to log10), sin, sinh, sqrt, tan, tanh </para>
		</listitem>
		</itemizedlist>
		</para>
		<para>Meaning of the parameters is as follows:</para>
		<itemizedlist>
		<listitem>
			<para><emphasis>expression</emphasis> (string) - a mathematical expression.
			</para>
		</listitem>
		<listitem>
			<para><emphasis>result_var</emphasis> (var) - variable which will
			hold the result of the evaluation.
			</para>
		</listitem>
		</itemizedlist>
		<para>
		This function can be used from any route.
		</para>
		<example>
		<title><function moreinfo="none">math_eval</function> usage</title>
		<programlisting format="linespecific">
...
# Compute some random math expression

$avp(1) = "3.141592";
$avp(2) = "2.71828";
$avp(3) = "123.45678";

if (math_eval("$avp(1) * ($avp(3) - ($avp(1) - $avp(2))) / $avp(3)", $avp(result))) {
	xlog("Result of expression: $avp(result)\n");
} else {
	xlog("Math eval failed!\n");
}

...
</programlisting>
		</example>
	</section>

	<section id="func_math_rpn" xreflabel="math_rpn()">
		<title>
		<function moreinfo="none">math_rpn(expression, result_var)</function>
		</title>
		<para>
		The function evaluates a given RPN expression and writes the result in the
		output variable.
		</para>
		<para>
    The expression is specified in Reverse Polish Notation. Values are pushed
    onto a stack, while operations are executed on that stack. The following operations
    are supported:
		<itemizedlist>
		<listitem>
			<para> binary operators: + - / * mod pow</para>
		</listitem>
		<listitem>
			<para> unary functions: neg exp ln log10 abs sqrt cbrt floor ceil round nearbyint trunc </para>
			<para> neg will change the sign of the top of the stack </para>
			<para> ln is natural logarithm; abs is absolute value; other functions are standard C functions </para>
		</listitem>
		<listitem>
			<para> constants: e pi</para>
		</listitem>
		<listitem>
			<para> stack manipulations commands: drop dup swap</para>
		</listitem>
		</itemizedlist>
		</para>
		<para>Meaning of the parameters is as follows:</para>
		<itemizedlist>
		<listitem>
			<para><emphasis>expression</emphasis> (string) - a RPN expression.
			</para>
		</listitem>
		<listitem>
			<para><emphasis>result_var</emphasis> (var) - variable which will
			hold the result of the evaluation.
			</para>
		</listitem>
		</itemizedlist>
		<para>
		This function can be used from any route.
		</para>
		<example>
		<title><function moreinfo="none">math_rpn</function> usage</title>
		<programlisting format="linespecific">
$avp(1) = "3";

if (math_rpn("1 $avp(1) swap swap dup drop / exp ln 1 swap /", $avp(result))) {
	xlog("Result of expression: $avp(result)\n");
} else {
	xlog("RPN eval failed!\n");
}

/* This example RPN script will push 1 then 3 onto the stack, then do a couple no-ops
(exchange the two values twice, duplicate one of them then drop the duplicate),
compute the division of 1 by 3, then do another no-op (exponentiation then logarithm), and
finally compute 1 divided by the result, giving 3 as the result. */
</programlisting>
		</example>
	</section>


	<section id="func_math_trunc" xreflabel="math_trunc()">
		<title>
		<function moreinfo="none">math_trunc(number, result_var)</function>
		</title>
		<para>
		Truncation of a number towards zero. This means that trunc(3.7) = 3.0 and
		trunc(-2.9) = -2.0. 
		</para>
		<para>Meaning of the parameters is as follows:</para>
		<itemizedlist>
		<listitem>
			<para><emphasis>number</emphasis> (string) - Number to be truncated.</para>
		</listitem>
		<listitem>
			<para><emphasis>result_var</emphasis> (var) - variable which will
			hold the result of the evaluation.
			</para>
		</listitem>
		</itemizedlist>
		<para>
		This function can be used from any route.
		</para>
		<example>
		<title><function moreinfo="none">math_trunc</function> usage</title>
		<programlisting format="linespecific">
...
# Truncate a random number

$avp(1) = "3.141492";

if (math_trunc($avp(1), $avp(result))) {
	xlog("Truncate result: $avp(result)\n");
} else {
	xlog("Truncate failed!\n");
}
...
</programlisting>
		</example>
	</section>

	<section id="func_math_floor" xreflabel="math_floor()">
		<title>
		<function moreinfo="none">math_floor(number, result_var)</function>
		</title>
		<para>
		Truncates a number, always towards -infinity. This means that floor(3.7) = 3.0
		and floor(-2.9) = -3.0
		</para>
		<para>Meaning of the parameters is as follows:</para>
		<itemizedlist>
		<listitem>
			<para><emphasis>number</emphasis> (string) - Number to be truncated.</para>
		</listitem>
		<listitem>
			<para><emphasis>result_var</emphasis> (var) - variable which will
			hold the result of the evaluation.
			</para>
		</listitem>
		</itemizedlist>
		<para>
		This function can be used from any route.
		</para>
		<example>
		<title><function moreinfo="none">math_floor</function> usage</title>
		<programlisting format="linespecific">
...
# Truncate a random number

$avp(1) = "3.141492";

if (math_floor($avp(1), $avp(result))) {
	xlog("Floor result: $avp(result)\n");
} else {
	xlog("Floor operation failed!\n");
}
...
</programlisting>
		</example>
	</section>

	<section id="func_math_ceil" xreflabel="math_ceil()">
		<title>
		<function moreinfo="none">math_ceil(number, result_var)</function>
		</title>
		<para>
		Truncates a number, always towards +infinity. This means that ceil(3.2) = 4.0
		and ceil(-2.9) = -2.0
		</para>
		<para>Meaning of the parameters is as follows:</para>
		<itemizedlist>
		<listitem>
			<para><emphasis>number</emphasis> (string) - Number to be truncated.</para>
		</listitem>
		<listitem>
			<para><emphasis>result_var</emphasis> (var) - variable which will
			hold the result of the evaluation.
			</para>
		</listitem>
		</itemizedlist>
		<para>
		This function can be used from any route.
		</para>
		<example>
		<title><function moreinfo="none">math_ceil</function> usage</title>
		<programlisting format="linespecific">
...
# Truncate a random number

$avp(1) = "3.141492";

if (math_ceil($avp(1), $avp(result))) {
	xlog("Ceil result: $avp(result)\n");
} else {
	xlog("Ceil operation failed!\n");
}
...
</programlisting>
		</example>
	</section>

	<section id="func_math_round" xreflabel="math_round()">
		<title>
		<function moreinfo="none">math_round(number, result_var[, decimals])</function>
		</title>
		<para>
		The round function returns the nearest integer, and tie-breaking is done away
		from zero. Examples: round(1.2) = 1.0, round(0.5) = 1.0, round(-0.5) = -1.0
		</para>
		<para>
		By default, the function returns an integer. An additional parameter controls
		the number of decimal digits of the initial number which will be kept. The
		rounding will then be done using the remaining decimal digits, and the result
		will be a float value, represented as a string.
		</para>
		<para>Meaning of the parameters is as follows:</para>
		<itemizedlist>
		<listitem>
			<para><emphasis>number</emphasis> (string) - Number to be rounded.</para>
		</listitem>
		<listitem>
			<para><emphasis>result_var</emphasis> - variable which will
			hold the result of the evaluation.
			</para>
		</listitem>
		<listitem>
			<para><emphasis>decimals</emphasis> (int, optional) -
			further improves the precision of the rounding.
			</para>
		</listitem>
		</itemizedlist>
		<para>
		This function can be used from any route.
		</para>
		<example>
		<title><function moreinfo="none">math_round</function> usage</title>
		<programlisting format="linespecific">
...
# Rounding PI

$avp(1) = "3.141492";

if (math_round($avp(1), $avp(result))) {

	# result should be: 3
	xlog("Round result: $avp(result)\n");
} else {
	xlog("Round operation failed!\n");
}

...

if (math_round($avp(1), $avp(result), 4)) {

	# result should be: "3.1415"
	xlog("Round result: $avp(result)\n");
} else {
	xlog("Round operation failed!\n");
}
...
</programlisting>
		</example>
	</section>

	<section id="func_math_round_sf" xreflabel="math_round_sf()">
		<title>
		<function moreinfo="none">math_round_sf(number, result_var, figures)</function>
		</title>
		<para>
		To give a simple explanation, rounding to N significant figures is done by 
		first obtaining the number resulted from keeping N significant figures
		(0 padded if necessary), then adjusting it if the N+1'th digit is greater
		or equal to 5.
		</para>
		<para>
		Some examples:
		<itemizedlist>
		<listitem>
			<para> round_sf(17892.987, 1) = 20000 </para>
			<para> round_sf(17892.987, 2) = 18000 </para>
			<para> round_sf(17892.987, 3) = 17900 </para>
			<para> round_sf(17892.987, 4) = 17890 </para>
			<para> round_sf(17892.987, 5) = 17893 </para>
			<para> round_sf(17892.987, 6) = 17893.0 </para>
			<para> round_sf(17892.987, 7) = 17892.99 </para>
		</listitem>
		</itemizedlist>
		</para>
		<para>Meaning of the parameters is as follows:</para>
		<itemizedlist>
		<listitem>
			<para><emphasis>number</emphasis> (string) - Number to be rounded.</para>
		</listitem>
		<listitem>
			<para><emphasis>result_var</emphasis> (var) - variable which will
			hold the result of the evaluation.
			</para>
		</listitem>
		<listitem>
			<para><emphasis>figures</emphasis> -
			further improves the precision of the rounding.
			</para>
		</listitem>
		</itemizedlist>
		<para>
		This function can be used from any route.
		</para>
		<example>
		<title><function moreinfo="none">math_round_sf</function> usage</title>
		<programlisting format="linespecific">
...
# Rounding PI

$avp(1) = "3.141492";

if (math_round_sf($avp(1), $avp(result), 4)) {

	# result should be: "3.141"
	xlog("Round result: $avp(result)\n");
} else {
	xlog("Round operation failed!\n");
}

...
</programlisting>
		</example>
	</section>

	<section id="func_math_compare" xreflabel="math_compare()">
		<title>
		<function moreinfo="none">math_compare(exp1, exp2, result_var)</function>
		</title>
		<para>
		Compare exp1 with exp2 and returns the comparison result in the result_var.
		Standard comparison return codes used : If exp1 > exp2, result_var = 1.
		Else if exp2 > exp1, result_var = -1, else (in case they are equal), 
		0 is populated in the result_var
		</para>
		<para>Meaning of the parameters is as follows:</para>
		<itemizedlist>
		<listitem>
			<para><emphasis>exp1</emphasis> (string) - First expression to be evaluated and used for comparison.</para>
		</listitem>
		<listitem>
			<para><emphasis>exp2</emphasis> (string) - Second expression to be evaluated and used for comparison.</para>
		</listitem>
		<listitem>
			<para><emphasis>result_var</emphasis> (var) - variable which will
			hold the result of the comparison.
			</para>
		</listitem>
		</itemizedlist>
		<para>
		This function can be used from any route.
		</para>
		<example>
		<title><function moreinfo="none">math_compare</function> usage</title>
		<programlisting format="linespecific">
...
# Rounding PI

$var(exp1) = "1 + 8";
$var(exp2) = "7/2";

if (math_compare($var(exp1), $var(exp2), $var(result))) {

	# $var(result) will be 1, since 9 > 3.5
}

...
</programlisting>
		</example>
	</section>
	</section>
</chapter>

