.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.40) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "Math::Symbolic::Compiler 3pm" .TH Math::Symbolic::Compiler 3pm "2021-01-07" "perl v5.32.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Math::Symbolic::Compiler \- Compile Math::Symbolic trees to Perl code .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use Math::Symbolic::Compiler; \& \& # A tree to compile \& my $tree = Math::Symbolic\->parse_from_string(\*(Aqa^2 + b * c * 2\*(Aq); \& \& # The Math::Symbolic::Variable \*(Aqa\*(Aq will be evaluated to $_[1], etc. \& my $vars = [qw(b a c)]; \& \& my ($closure, $code, $trees) = \& Math::Symbolic::Compiler\->compile($tree, $vars); \& \& print $closure\->(2, 3, 5); # (b, a, c) \& # prints 29 (= 3^2 + 2 * 5 * 2) \& \& # or: \& ($closure, $trees) = \& Math::Symbolic::Compiler\->compile_to_sub($tree, $vars); \& \& ($code, $trees) = Math::Symbolic::Compiler\->compile_to_code($tree, $vars); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This module allows one to compile Math::Symbolic trees to Perl code and/or anonymous subroutines whose arguments will be positionally mapped to the variables of the compiled Math::Symbolic tree. .PP The reason you'd want to do this is that evaluating a Math::Symbolic tree to its numeric value is extremely slow. So is compiling, but once you've done all necessary symbolic calculations, you can take advantage of the speed gain of invoking a closure instead of evaluating a tree. .SS "\s-1UNCOMPILED LEFTOVER TREES\s0" .IX Subsection "UNCOMPILED LEFTOVER TREES" Not all, however, is well in the land of compiled Math::Symbolic trees. There may occasionally be trees that cannot be compiled (such as a derivative) which need to be included into the code as trees. These trees will be returned in a referenced array by the compile*() methods. The closures will have access to the required trees as a special variable '@_TREES inside the closure's scope, so you need not worry about them in that case. But if you plan to use the generated code itself, you need to supply an array named \f(CW@_TREES\fR that contains the trees as returned by the compile*() methods in the scope of the \fBeval()\fR you evaluate the code with. .PP Note that you give away all performance benefits compiling the tree might have if the closure contains uncompiled trees. You can tell there are any by checking the length of the referenced array that contains the trees. If it's 0, then there are no trees left to worry about. .SS "\s-1AVOIDING LEFTOVER TREES\s0" .IX Subsection "AVOIDING LEFTOVER TREES" In most cases, this is pretty simple. Just apply all derivatives in the tree to make sure that there are none left in the tree. As of version 0.130, there is no operator except derivatives that cannot be compiled. There may, however, be some operators you cannot get rid of this easily some time in the future. If you have problems getting a tree to compile, try using the means of simplification provided by Math::Symbolic::* to get a simpler tree for compilation. .SS "\s-1EXPORT\s0" .IX Subsection "EXPORT" None by default, but you may choose to import the \fBcompile()\fR, \fBcompile_to_sub()\fR, and \fBcompile_to_code()\fR subroutines to your namespace using the standard Exporter semantics including the ':all' tag. .SH "SUBROUTINES" .IX Header "SUBROUTINES" .ie n .SS "($code, $trees) = compile_to_code($tree, $vars)" .el .SS "($code, \f(CW$trees\fP) = compile_to_code($tree, \f(CW$vars\fP)" .IX Subsection "($code, $trees) = compile_to_code($tree, $vars)" The \fBcompile_to_code()\fR class method takes one mandatory argument which is the Math::Symbolic tree to be compiled. Second argument is optional and an array reference to an array of variable mappings. See \*(L"\s-1VARIABLE PASSING STYLES\*(R"\s0 for details on how this works. .PP \&\fBcompile_to_code()\fR returns a string and an array reference. The string contains the compiled Perl code that uses the values stored in \f(CW@_\fR as described in the section on positional variable passing. It also accesses a special variable \f(CW@_TREES\fR if there were any sub-trees (inside the tree that has been compiled) that were impossible to compile. The array reference returned by this method contains any of the aforementioned trees that failed to compile. .PP If there are any such trees that did not compile, you may put them into the \&\f(CW@_TREES\fR variable in scope of the \fBeval()\fR that evaluates the compiled code in the same order that they were returned by this method. If you do that, the code will run and determine the value of the tree at run-time. Needless to say, that is slow. .ie n .SS "($sub, $trees) = compile_to_sub($tree, $vars)" .el .SS "($sub, \f(CW$trees\fP) = compile_to_sub($tree, \f(CW$vars\fP)" .IX Subsection "($sub, $trees) = compile_to_sub($tree, $vars)" The \fBcompile_to_sub()\fR class method takes one mandatory argument which is the Math::Symbolic tree to be compiled. Second argument is optional and an array reference to an array of variable mappings. See \*(L"\s-1VARIABLE PASSING STYLES\*(R"\s0 for details on how this works. .PP \&\fBcompile_to_sub()\fR returns a list of two elements, the first being the compiled anonymous subroutine. For details on the second element, please refer to the docs on the \fBcompile_to_code()\fR subroutine. .ie n .SS "($sub, $code, $trees) = compile($tree, $vars)" .el .SS "($sub, \f(CW$code\fP, \f(CW$trees\fP) = compile($tree, \f(CW$vars\fP)" .IX Subsection "($sub, $code, $trees) = compile($tree, $vars)" The \fBcompile()\fR class method takes one mandatory argument which is the Math::Symbolic tree to be compiled. Second argument is optional and an array reference to an array of variable mappings. See \*(L"\s-1POSITIONAL VARIABLE PASSING\*(R"\s0 for details on how this works. .PP \&\fBcompile()\fR returns a list of three elements, the first being the compiled anonymous subroutine, the second being the compiled code. For details on the second and third elements, please refer to the docs on the \fBcompile_to_code()\fR subroutine. .SS "\s-1VARIABLE PASSING STYLES\s0" .IX Subsection "VARIABLE PASSING STYLES" Currently, the Math::Symbolic compiler only supports compiling to subs with positional variable passing. At some point, the user should be able to choose between positional\- and named variable passing styles. The difference is best explained by an example: .PP .Vb 2 \& # positional: \& $sub\->(4, 5, 1); \& \& # named: (NOT IMPLEMENTED!) \& $sub\->(a => 5, b => 4, x => 1); .Ve .PP With positional variable passing, the subroutine statically maps its arguments to its internal variables. The way the subroutine does that has been fixed at compile-time. It is determined by the second argument to the various compile_* functions found in this package. This second argument is expected to be a reference to an array of variable names. The order of the variable names determines which parameter of the compiled sub will be assigned to the variable. Example: .PP .Vb 2 \& my ($sub) = \& Math::Symbolic::Compiler\->compile_to_sub($tree, [qw/c a b/]); \& \& # First argument will be mapped to c, second to a, and third to b \& # All others will be ignored. \& $sub\->(4, 5, 6, 7); \& \& # Variable mapping: a = 5, b = 6, c = 4 .Ve .PP One important note remains: if any (or all) variables in the tree are unaccounted for, they will be lexicographically sorted and appended to the variable mapping in that order. That means if you don't map variables yourself, they will be sorted lexicographically. .PP Thanks to Henrik Edlund's input, it's possible to pass a hash reference as second argument to the compile* functions instead of an array reference. The order of the mapped variables is then determined by their associated value, which should be an integer starting with 0. Example: .PP .Vb 1 \& Math::Symbolic::Compiler\->compile_to_sub($tree, {b => 2, a => 1, c => 0}); .Ve .PP Would result in the order c, a, b. .SH "AUTHOR" .IX Header "AUTHOR" Please send feedback, bug reports, and support requests to the Math::Symbolic support mailing list: math-symbolic-support at lists dot sourceforge dot net. Please consider letting us know how you use Math::Symbolic. Thank you. .PP If you're interested in helping with the development or extending the module's functionality, please contact the developers' mailing list: math-symbolic-develop at lists dot sourceforge dot net. .PP List of contributors: .PP .Vb 3 \& Steffen MXller, symbolic\-module at steffen\-mueller dot net \& Stray Toaster, mwk at users dot sourceforge dot net \& Oliver EbenhXh .Ve .SH "SEE ALSO" .IX Header "SEE ALSO" New versions of this module can be found on http://steffen\-mueller.net or \s-1CPAN.\s0 The module development takes place on Sourceforge at http://sourceforge.net/projects/math\-symbolic/ .PP Math::Symbolic