Reference

Limitations

Everything on this page is a thing the library does not do, does imperfectly, or does in a way that will surprise you. It is here so you find out now rather than at two in the morning.

Where a limit has a workaround, the workaround is given. Where it does not, that is said plainly.

Numbers

The last bit depends on how you build

Extended is 10 bytes on 32-bit Delphi and on FPC for Linux, and 8 bytes - the same as Double - on 64-bit Windows. The parser keeps intermediates in Extended, so a long chain can end on a different last bit depending on the target.

Concretely: 0.1 + 0.2 ends in ...3333 on the first pair and ...3334 on the second. Both are correct roundings of different intermediate precision. If you need one answer everywhere, round explicitly at the end.

Fractional powers under FPC on 64-bit Windows

2 ** 0.5 should equal sqrt(2) to the last bit. Under Delphi and under FPC on Linux it does. Under FPC on 64-bit Windows it misses by 337 units in the last place, because Power there computes exp(y × ln x) without the extra precision the other targets have.

Use sqrt for square roots and intpower for whole exponents, both of which are exact.

Text

Names and string parameters live in a fixed buffer of 4 096 characters. Anything longer is truncated silently - no exception, no warning. In practice a formula never comes close, but a generated one might. The registry also weighs more than it should because of this: roughly 900 KB per parser instance with the full function set registered.

Changing this means moving the registry to dynamic strings and a new serialisation format. It is planned, not done.

The accelerator

Does notConsequence
Run anywhere but x86-64on ARM or 32-bit targets the machine-code stage is skipped; the portable IR is tried next, with the ordinary interpreter as the final fallback. The measured IR figures are in jit/README.md
Compile functions that take parametersmean, poly and friends fall back
Key its cache by shapetwo formulas differing only in a constant compile twice

Threads

TMathParser. Evaluation is thread-safe once everything is registered. Registration itself is not: adding a function or a variable while another thread is evaluating is undefined. The contract is simple and worth stating - register everything before the first evaluation, then evaluate from as many threads as you like.

TJitParser is different, and the difference matters. The accelerator keeps a cache: the text of the last formula, a list of compiled entries and the counters beside it, all written on the first sight of a formula and none of it under a lock. Two threads meeting a formula the cache has not seen will both compile it and both write the list. One accelerating parser therefore belongs to one thread.

To evaluate in parallel, compile the scripts up front on a single thread with CompileScript, then execute them. Executing a prepared TJitScript does not modify it, so one script may run on several threads at once - but only as far as everything it reaches allows that: the variables it reads have to be safe to read concurrently, and so does every function it calls. Both are yours, not the library's.

The addresses are baked in when the script is built: the redirect chain is resolved once, at compile time. So a thread that needs its own variables needs its own script, with its own category, compiled separately - Copy the script, redirect the copy, compile that.

Plotting

LimitDetail
Antialiasingsmooth curves use GDI+, which exists only in the Delphi build; FPC draws a plain polyline
Reportroots and areas are found numerically on the sampled points, so their accuracy follows the sampling density
Polar polesa curve through infinity is broken rather than joined - correct, but it means one curve may arrive as several pieces
Loop budget in the browserone budget covers a whole sweep, not each point, so an endless loop cannot hold the tab for as many turns as there are points. A formula with an honest loop can spend it partway along, and the remaining points come back as "not a number". The demo says so rather than leaving a silent gap; the plugin has no such limit

What is deliberately absent

There is no complex arithmetic, no matrices, no units of measurement, and no symbolic algebra beyond deriv. Adding any of them is possible through the function registry; none is built in.