This repo contains routines for evaluating mathematical expressions contained in strings, e.g., cos((a+b)^2+1.6*log(c))
. It is a modernized version of the code developed by George Benthien.
I came across George's code while working on benchmark.f. I created an example which contains all the equation parsers I could find and I was impressed by the performances of the present code. I decided to give it a bit more visibility by creating this repo and started to work on some modernization. It is now up-to-date, fully type-explicit, and fpm-compatible.
The strings expressions can contain numbers (e.g., 1.5
or 1.5e6
), previously defined parameters (like a
,b
, c
above), arithmetic operators (+
,-
,*
,/
,^
, **
), and any of the functions (sin
, cos
, tan
, log10
, log
, abs
, exp
, sqrt
, real
, imag
, conjg
, and ang
). They can also contain nested levels of parentheses. The module also contains routines for defining and retrieving user-specified parameters. The quantity pi
and the imaginary unit i
are pre-defined parameters.
To build that library you need
The following compilers are tested on the default branch of evaluate.f:
Name | Version | Platform | Architecture |
---|---|---|---|
GCC Fortran (MinGW) | 14 | Windows 10 | x86_64 |
Intel oneAPI classic | 2021.5 | Windows 10 | x86_64 |
Unit test rely on the the header file assertion.inc
. Since the whole framework fits in a single file, it has been added directly to the repo.
Linting, indentation, and styling is done with fprettify with the following settings
The user can assign values to parameters that can be used in expressions with the subroutine defparam
. The calling syntax is
where symbol is the desired parameter name; value is a real, integer, or complex variable (single or double precision); and expr is a string containing an expression to be evaluated. The value obtained by evaluating the expression expr is associated with the parameter symbol. Parameter names must begin with a letter (a-z, A-Z) and must not be longer than 24 characters. Parameter names are not case dependent.
An expression can be evaluated with the subroutine eval
. The calling syntax is
where expr is a string containing the expression to be evaluated; value is the result (single or double precision real, complex or integer). The expression can contain the arithmetic operations +
, -
, *
, /
, **
or ^
as well as the functions sin
, cos
, tan
, log10
, log
, abs
, exp
, sqrt
, real
, imag
, conjg
, and ang
(the function ang calculates the phase angle of its complex argument). The expression can also contain numerical values and previously defined parameters
Grouping by nested levels of parentheses is also allowed. The parameters pi
and i
(imaginary unit) are predefined. Complex numbers can be entered as a+i*b
if the parameter i
has not been redefined by the user. Complex numbers can also be entered using complex(a,b)
.
Example expression:
The value assigned to a symbol can be retrieved using the subroutine getparam
. The calling syntax is:
where sym is a symbol string; value is a numeric variable (any of the six standard types).
The symbols and their values in the symbol table can be listed using the subroutine listvar
. The variable ierr is always available following a call to any of the above subroutines and is zero if there were no errors. The possible nonzero values for ierr are:
Value | Definition |
---|---|
1 | Expression empty |
2 | Parentheses don't match |
3 | Number string does not correspond to a valid number |
4 | Undefined symbol |
5 | Less than two operands for binary operation |
6 | No operand for unary plus or minus operators |
7 | No argument(s) for function |
8 | Zero or negative real argument for logarithm |
9 | Negative real argument for square root |
10 | Division by zero |
11 | Improper symbol format |
12 | Missing operator |
13 | Undefined function |
14 | Argument of tangent function a multiple of pi/2 |
The repo is compatible with fpm projects. It can be build using fpm
For convenience, the repo also contains a response file that can be invoked as follows:
(For the Windows users, that command does not work in Powershell since '@' is a reserved symbol. One should use the '–' as follows: fpm --% @build
. This is linked to the following issue)
Building with ifort requires to specify the compiler name (gfortran by default)
Alternatively, the compiler can be set using fpm environment variables.
Besides the build command, several commands are also available:
The settings to the cpp preprocessor are specified in the file.
The _FPM
macro is used to differentiate the build when compiling with fpm or Visual Studio. This is mostly present to adapt the hard coded paths that differs in both cases.
The project was originally developed on Windows with Visual Studio 2019. The repo contains the solution file (Evaluate.sln) to get you started with Visual Studio 2019.
Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated. So, thank you for considering contributing to evaluate.f. Please review and follow these guidelines to make the contribution process simple and effective for all involved. In return, the developers will help address your problem, evaluate changes, and guide you through your pull requests.
By contributing to evaluate.f, you certify that you own or are allowed to share the content of your contribution under the same license.
Please follow the style used in this repository for any Fortran code that you contribute. This allows focusing on substance rather than style.
A bug is a demonstrable problem caused by the code in this repository. Good bug reports are extremely valuable to us—thank you!
Before opening a bug report:
A good bug report should include all information needed to reproduce the bug. Please be as detailed as possible:
This information will help the developers diagnose the issue quickly and with minimal back-and-forth.
If you have a suggestion that would make this project better, please create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!
git checkout -b feature/AmazingFeature
)git commit -m 'Add some AmazingFeature'
)git push origin feature/AmazingFeature
)Fixes #<issue-number>
. If your PR implements a feature that adds or changes the behavior of evaluate.f, your PR must also include appropriate changes to the documentation and associated units tests.In brief,
Distributed under the MIT License.