How Mathematical Expressions are Treated in the Script Language of RP Photonics Software
Posted on 2013-10-02 in the RP Photonics Software News (available as e-mail newsletter!)
Permanent link: https://www.rp-photonics.com/software_news_2013_10_02.html
Abstract: This post explains how the processing of mathematical expressions works in the script language of software by RP Photonics. Although the user does not need to know that, it may be interesting to look behind the scenes.
Today, I would like to give you some insight on how our software works internally in the context of mathematical expressions, handled by our script language. Although as a user you do not need to know such things, it may be interesting to look behind the scenes.
When you generate some plot, you might use some code like the following e.g. in RP Fiber Power:
diagram 1: "Amplifier Gain vs. Pump Power" x: 0, 400 "pump power (mW), @x y: 0, 30 "amplifier gain (dB)", @y f: (set_P_in(pump, x * mW); 10 * lg(P_out(signal) / P_s_in))
The last line defines the plot, which is based on a mathematical expression. For each x position, its evaluation will imply that the pump power is set, the new signal output power is calculated, and the gain in decibels is calculated from that power.
But how is that really done? Obviously, the program must be able to read mathematical expressions, for example, understand their structure, store them in some suitable form, and evaluate them later on as needed. What is really does:
- When a mathematical expression is read, its details are stored in the form of a tree structure. For example, if the expression is sin(pi*x), the expression has a node for the sine function. That function, having a single argument, points to a “*” node (multiplication). That one has two operands, i.e., points to two other nodes: one with the constant π, another one with the variable x. Here, x is actually a parameter, the value of which will be stored on a stack (rather than the table of global variables). See the illustration on the right side.
- Later on, when the plot is made, that structure can be evaluated efficiently. For each x value, the corresponding value is put on the stack. Then, the “sin” node is asked to return its result. Of course, it takes the value of is argument, calculates the sine, and returns that. Its argument, the “*” node, itself calls for the two operand values and returns their product.
Of course, that was only a simple example. You can imagine that there are more complicated types of nodes – for example, for functions with multiple arguments and parameters (doing integrations), blocks of expressions with constants and local variables, etc. There are around 130 standard functions for the arithmetics. In addition, there are many additional predefined functions for the physics. In RP Fiber Power, for example, there are 247 functions, for example for defining and modifying a fiber amplifier or laser model and for retrieving calculated results.
You can easily imagine that it takes some time to implement all that – and why our competitors don't just equip their products with a script language as well! It surely takes more than Friday afternoon to do such a thing. However, the script language is the key for absolutely flexible use of our software: the end user can program anything himself or herself, without having to deal with the source code. For example, the user can define any kind of plot – not only select one of those which we anticipated.
You may wonder how the speed of script evaluation compares with direct programming, e.g. with Delphi (the development system we use). When some complex mathematical expressions are evaluated, it is several times slower. However, note that most of the computation time is often spent within predefined functions, where plain Delphi-generated code is executed. For example, one may need some Fourier transforms (FFT algorithm) in a script, and these are of course not implemented with script code, but with a predefined function, which works quite efficiently. Therefore, the speed of execution is in practice often not much lower than if you would implement all the things directly with Delphi, C++ or C#. And your speed and efficiency is certainly much higher. This is what counts in the end, of course.