# Feq-parse Updates - Evaluation with arrays now supported!

**URL:** <https://fortran-lang.discourse.group/t/feq-parse-updates-evaluation-with-arrays-now-supported/6871>\
**Category:** Announcements\
**Created:** [November 27, 2023, 6:41pm UTC](https://fortran-lang.discourse.group/t/feq-parse-updates-evaluation-with-arrays-now-supported/6871 "2023-11-27T18:41:20Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![fluidnumerics\_joe](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/fluidnumerics_joe/32/4360_2.png) [@fluidnumerics\_joe](https://fortran-lang.discourse.group/u/fluidnumerics_joe)\
**Post date:** [November 27, 2023, 6:41pm UTC](https://fortran-lang.discourse.group/t/feq-parse-updates-evaluation-with-arrays-now-supported/6871/1 "2023-11-27T18:41:20Z")

</div>

**Summary**  
For those who are new to [feq-parse](https://github.com/FluidNumerics/feq-parse), this package allows users to define functions as character strings and evaluate them on-the-fly. In earlier versions of feq-parse, only scalar inputs were accepted to the `evaluate` methods. When working with Fortran arrays, this required a do-loop around the `evaluate` call which would re-evaluate the parser objects each time; this is slow! The latest updates on the master branch allow for you to pass 1-D arrays to the `evaluate` methods, which provides significantly improved performance for evaluation of functions on arrays of independent variables. In a simple example, evaluating a gaussian on 10 million points, we show ~30x speedup with this new feature.

While implementing this new feature, I’ve also added to the test suite and started tracking code coverage (we’re hitting 92% coverage as of today!), which is now noted in the [README](https://github.com/FluidNumerics/feq-parse#fortran-equation-parser). From here, I am working on adding support for higher dimension arrays and will then work on GPU accelerated back-ends for the supported operator and function evaluations for even faster equation evaluation!

**Scalar v. Array performance**  
As an example, consider the following program, where we set up an equation parser object and evaluate it at 10 million points by calling the `evaluate` method for each point; this is how we had to do equation evaluations with earlier versions of feq-parse.

```auto
program array_with_scalar_eval

  use FEQParse

  implicit none
  integer,parameter :: N = 10000000
  type(EquationParser) :: f
  character(LEN=1),dimension(1) :: independentVars
  character(LEN=30) :: eqChar
  real :: x(1)
  real :: feval(1:N)
  integer :: i
  real :: t1,t2

  ! Specify the independent variables
  independentVars = (/'x'/)

  ! Specify an equation string that we want to evaluate
  eqChar = 'f = \exp( -(x^2) )'

  ! Create the EquationParser object
  f = EquationParser(eqChar,independentVars)

  ! Evaluate the equation
  call cpu_time(t1)
  do i = 1,N
    x(1) = -1.0_real32 + (2.0_real32)/real(N,real32)*real(i - 1,real32)
    feval(i) = f % evaluate(x)
  end do
  call cpu_time(t2)
  print *, "runtime :", (t2 - t1)," s"

  ! Clean up memory
  call f % Destruct()

end program array_with_scalar_eval

```

Compiling and running this example (with gfortran 11.4.0) gives a runtime for the main loop as ~8.1 s

```auto
./array_with_scalar_eval 
 runtime : 8.11188793 s

```

With the updated version of feq-parse, we can instead pre-load an array for all of the values of `x` and call the `evaluate` method once. This example is shown below.

```auto
program array_with_array_eval

  use FEQParse

  implicit none
  integer,parameter :: N = 10000000
  type(EquationParser) :: f
  character(LEN=1),dimension(1) :: independentVars
  character(LEN=30) :: eqChar
  real :: x(1:N,1)
  real :: feval(1:N)
  integer :: i
  real :: t1,t2

  ! Specify the independent variables
  independentVars = (/'x'/)

  ! Specify an equation string that we want to evaluate
  eqChar = 'f = \exp( -(x^2) )'

  ! Create the EquationParser object
  f = EquationParser(eqChar,independentVars)

  ! Evaluate the equation
  call cpu_time(t1)
  do i = 1,N
    x(i,1) = -1.0_real32 + (2.0_real32)/real(N,real32)*real(i - 1,real32)
  end do
  feval = f % evaluate(x)
  call cpu_time(t2)
  print *, "runtime :", (t2 - t1)," s"

  ! Clean up memory
  call f % Destruct()

end program array_with_array_eval

```

Compiling and running this example (with the same compiler and on the same system) gives a runtime of ~0.27 s ( **~30x speedup** )

```auto
./array_with_array_eval 
 runtime : 0.270846009 s

```

---

<div class="post-metadata">

**Author:** ![vmagnin](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/vmagnin/32/28_2.png) [@vmagnin](https://fortran-lang.discourse.group/u/vmagnin)\
**Post date:** [November 27, 2023, 7:28pm UTC](https://fortran-lang.discourse.group/t/feq-parse-updates-evaluation-with-arrays-now-supported/6871/2 "2023-11-27T19:28:09Z")

</div>

It looks great.

Note that there is a little bug in the tests:

```bash
$ fpm test
test.f90 failed.
[1%] Compiling...
test/test.f90:76:24:

   76 | end program testinclude "abs_r1fp32.f90"
      | 1
Error: Expected label ‘test’ for END PROGRAM statement at (1)
compilation terminated due to -fmax-errors=1.
<ERROR> Compilation failed for object " test_test.f90.o "
<ERROR> stopping due to failed compilation
STOP 1
vmagnin@PC2:/tmp/feq-parse$ fpm run
<INFO> No executables to run
STOP 0

```

There is indeed an include command that was accidentally pasted line 76. The tests run OK after fixing it.

And maybe you could include the example of the README.md in a `example/` directory, so that it could be launched with `fpm run --example`. And `auto-examples = true` in the manifest.

---

<div class="post-metadata">

**Author:** ![fluidnumerics\_joe](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/fluidnumerics_joe/32/4360_2.png) [@fluidnumerics\_joe](https://fortran-lang.discourse.group/u/fluidnumerics_joe)\
**Post date:** [November 27, 2023, 7:35pm UTC](https://fortran-lang.discourse.group/t/feq-parse-updates-evaluation-with-arrays-now-supported/6871/3 "2023-11-27T19:35:59Z")

</div>

I’ll add the fpm tests to the CI suite. At the moment, I’m only testing with `ctest`

---

<div class="post-metadata">

**Author:** ![fluidnumerics\_joe](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/fluidnumerics_joe/32/4360_2.png) [@fluidnumerics\_joe](https://fortran-lang.discourse.group/u/fluidnumerics_joe)\
**Post date:** [November 27, 2023, 11:21pm UTC](https://fortran-lang.discourse.group/t/feq-parse-updates-evaluation-with-arrays-now-supported/6871/4 "2023-11-27T23:21:55Z")

</div>

Examples have been added in the `example/` subdirectory and the `fpm.toml` has been updated to include these examples. Additionally, a test has been added to install, test, and run examples with fpm. Thanks for the feedback @vmagnin !

> <https://github.com/FluidNumerics/feq-parse/pull/6>
>
> Fixing issues brought up in discussion at \[Fortran Lang Discourse\](https://fortr…an-lang.discourse.group/t/feq-parse-updates-evaluation-with-arrays-now-supported/6871/2?u=fluidnumerics\_joe)

---

<div class="post-metadata">

**Author:** ![vmagnin](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/vmagnin/32/28_2.png) [@vmagnin](https://fortran-lang.discourse.group/u/vmagnin)\
**Post date:** [November 28, 2023, 8:57am UTC](https://fortran-lang.discourse.group/t/feq-parse-updates-evaluation-with-arrays-now-supported/6871/5 "2023-11-28T08:57:13Z")

</div>

@fluidnumerics_joe , I have successfully run the tests and the three examples. The interest of the `example` directory is that lazy people like me can immediately start playing with the library by modifying these codes.

---

<div class="post-metadata">

**Author:** ![fluidnumerics\_joe](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/fluidnumerics_joe/32/4360_2.png) [@fluidnumerics\_joe](https://fortran-lang.discourse.group/u/fluidnumerics_joe)\
**Post date:** [November 28, 2023, 3:05pm UTC](https://fortran-lang.discourse.group/t/feq-parse-updates-evaluation-with-arrays-now-supported/6871/6 "2023-11-28T15:05:46Z")

</div>

Excellent! As I work up features, I’ll keep it in mind to add to the examples.

---

<div class="post-metadata">

**Author:** ![ivanpribec](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/ivanpribec/32/3290_2.png) [@ivanpribec](https://fortran-lang.discourse.group/u/ivanpribec)\
**Post date:** [November 30, 2023, 1:14am UTC](https://fortran-lang.discourse.group/t/feq-parse-updates-evaluation-with-arrays-now-supported/6871/7 "2023-11-30T01:14:08Z")

</div>

Looking into the implementation, I was wondering if the evaluate function could be made `elemental`? From the top of my head, I can’t recall if there are any rules against making member methods elemental.

Another thought I had was, which methods of the equation parser (if any) are overridable, and would this make it possible to implement custom operators?

```auto
  TYPE EquationParser
! ...
    CONTAINS

      PROCEDURE :: Destruct => Destruct_EquationParser
      PROCEDURE :: CleanEquation
      PROCEDURE :: Tokenize
      PROCEDURE :: ConvertToPostfix

      GENERIC :: Evaluate => Evaluate_sfp32, Evaluate_sfp64, &
                             Evaluate_r1fp32, Evaluate_r1fp64
      PROCEDURE, PRIVATE :: Evaluate_sfp32, Evaluate_sfp64
      PROCEDURE, PRIVATE :: Evaluate_r1fp32, Evaluate_r1fp64

      PROCEDURE :: Print_InFixTokens
      PROCEDURE :: Print_PostFixTokens

      procedure, private :: Priority

  END TYPE EquationParser

  INTERFACE EquationParser
    PROCEDURE Construct_EquationParser
  END INTERFACE EquationParser

```

For example, could I implement a (custom) calculus on top of this?

```fortran
eqChar = "f = div( D * grad(u))'"

```

The [Dedalus](https://dedalus-project.org/index.html) spectral solver (in Python) has something like this.

---

<div class="post-metadata">

**Author:** ![fluidnumerics\_joe](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/fluidnumerics_joe/32/4360_2.png) [@fluidnumerics\_joe](https://fortran-lang.discourse.group/u/fluidnumerics_joe)\
**Post date:** [November 30, 2023, 2:20am UTC](https://fortran-lang.discourse.group/t/feq-parse-updates-evaluation-with-arrays-now-supported/6871/8 "2023-11-30T02:20:33Z")

</div>

The issue with using an `elemental` for the `evaluate` generic ( I think ) is that this procedure calls `Push` for various “float stacks” (e.g. [Scalar fp32](https://github.com/FluidNumerics/feq-parse/blob/master/src/FEQParse.F90#L449) and [Rank 1 fp32](https://github.com/FluidNumerics/feq-parse/blob/master/src/FEQParse.F90#L669) ) and `f_of_x` for each type ( e.g. [Scalar fp32](https://github.com/FluidNumerics/feq-parse/blob/master/src/FEQParse.F90#L490) and [Rank 1 fp32](https://github.com/FluidNumerics/feq-parse/blob/master/src/FEQParse.F90#L490) ). Though upon writing this, I suppose the `push` and `pop` procedures for the float stacks could be elemental as well as the `f_of_x`, which could cut down on the number of lines of code significantly here. Having the `generic` evaluate will still be needed, given plans to support passing `c_ptr`’s in for evaluation on the GPU. At any rate, I’ll kick off another branch and see if that would work.

At the moment, the available functions are hard coded in the [`construct` method for the `FEQParse_Functions` class](https://github.com/FluidNumerics/feq-parse/blob/master/src/FEQParse_Functions.F90#L58). Though I think we could add a class for user-defined functions that allows one to map a character to a procedure through a procedure pointer. Opened an issue here to explore this more ( [Add support for user-defined functions · Issue #10 · FluidNumerics/feq-parse · GitHub](https://github.com/FluidNumerics/feq-parse/issues/10) )

Thanks for the feedback!

---

<div class="post-metadata">

**Author:** ![Arjen](https://avatars.discourse-cdn.com/v4/letter/a/b9bd4f/32.png) [@Arjen](https://fortran-lang.discourse.group/u/Arjen)\
**Post date:** [November 30, 2023, 10:16am UTC](https://fortran-lang.discourse.group/t/feq-parse-updates-evaluation-with-arrays-now-supported/6871/9 "2023-11-30T10:16:02Z")

</div>

Nice to see the developments for this package. I have not had an opportunity yet to use it in earnest, but I do have an application in mind. One thing, though, not criticism, just a remark: if you use it to evaluate an array, then all variables should be arrays, right? No possibilty to combine a scalar with an array? Something along these lines:

```auto
real :: a(100)
real :: b

...
expression = 'exp( -b * a)'
...
write(*,*) f%evaluate( x )

```

---

<div class="post-metadata">

**Author:** ![fluidnumerics\_joe](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/fluidnumerics_joe/32/4360_2.png) [@fluidnumerics\_joe](https://fortran-lang.discourse.group/u/fluidnumerics_joe)\
**Post date:** [November 30, 2023, 11:46am UTC](https://fortran-lang.discourse.group/t/feq-parse-updates-evaluation-with-arrays-now-supported/6871/10 "2023-11-30T11:46:41Z")

</div>

@Arjen - Correct. Input matches output in type, kind, and rank, aside from the extra dimension for input independent variables.

I’m not sure I understand your example, though; what is `x` ? are `b` and `a` declared as independent variables for the parser ? The parser does support multiplication, addition, subtraction, and exponentiation of arrays with constants… I’d have to think about how to have “variable” scalars, though. Issue opened here - [Mix input types, e.g. scalars with arrays · Issue #11 · FluidNumerics/feq-parse · GitHub](https://github.com/FluidNumerics/feq-parse/issues/11)

Thanks for the feedback

---

<div class="post-metadata">

**Author:** ![fluidnumerics\_joe](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/fluidnumerics_joe/32/4360_2.png) [@fluidnumerics\_joe](https://fortran-lang.discourse.group/u/fluidnumerics_joe)\
**Post date:** [November 30, 2023, 11:49am UTC](https://fortran-lang.discourse.group/t/feq-parse-updates-evaluation-with-arrays-now-supported/6871/11 "2023-11-30T11:49:56Z")

</div>

> [@Arjen](#):
>
> Nice to see the developments for this package.

It’s been work just trying to find time to work on projects that are made freely available for anyone to use (paying customers always come first). If you haven’t already, give the repo a star on github, so that we can work toward getting development sponsored on open collective.

---

<div class="post-metadata">

**Author:** ![Arjen](https://avatars.discourse-cdn.com/v4/letter/a/b9bd4f/32.png) [@Arjen](https://fortran-lang.discourse.group/u/Arjen)\
**Post date:** [December 1, 2023, 8:20am UTC](https://fortran-lang.discourse.group/t/feq-parse-updates-evaluation-with-arrays-now-supported/6871/12 "2023-12-01T08:20:25Z")

</div>

I wanted to cut some corners, so I only presented an abbreviation of an example.

I will try and experiment a bit, because the application I very vaguely have in mind, may require some “introspection”. I better try and assemble my requirements 🙂

---

<div class="post-metadata">

**Author:** ![Arjen](https://avatars.discourse-cdn.com/v4/letter/a/b9bd4f/32.png) [@Arjen](https://fortran-lang.discourse.group/u/Arjen)\
**Post date:** [December 1, 2023, 9:48am UTC](https://fortran-lang.discourse.group/t/feq-parse-updates-evaluation-with-arrays-now-supported/6871/13 "2023-12-01T09:48:29Z")

</div>

Okay, I had some time to build the library and one of the examples. It did not work “out-of-the-hox”: I used Intel oneAPI Fortran and MS Visual Studio on WIndows. There were a bunch of build errors. I will report them in more detail later - in the github project.  
One thing I am interested in is whether it is possbile to extract the variable names. Related: I see that an unregistered variable causes an error message, but is it possible to catch that?  
Oh, I also found a few bugs: I extended the scalar example with an extra variable, registered that, but got the wrong answer. And changing the expression led to a series of warnings “Attempt to pop from empty token stack”. I will report on that in the github project as well.

---

<div class="post-metadata">

**Author:** ![fluidnumerics\_joe](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/fluidnumerics_joe/32/4360_2.png) [@fluidnumerics\_joe](https://fortran-lang.discourse.group/u/fluidnumerics_joe)\
**Post date:** [December 1, 2023, 10:51am UTC](https://fortran-lang.discourse.group/t/feq-parse-updates-evaluation-with-arrays-now-supported/6871/14 "2023-12-01T10:51:07Z")

</div>

I’ll add `ifx` as well as windows OS to the GitHub actions tests. If you can provide some feedback on what you did to get it to build, that would be helpful and could save some time.

I’m certain it’s possible to catch unregistered variables. I’ll likely add this to the `CleanEquation` step which will return an error code during construction for the end user to manage.

With regards to your error, a minimal reproducer is helpful here; we can add that to the examples or tests.

This is very helpful feedback! Thank you!

---

<div class="post-metadata">

**Author:** ![Arjen](https://avatars.discourse-cdn.com/v4/letter/a/b9bd4f/32.png) [@Arjen](https://fortran-lang.discourse.group/u/Arjen)\
**Post date:** [December 1, 2023, 11:07am UTC](https://fortran-lang.discourse.group/t/feq-parse-updates-evaluation-with-arrays-now-supported/6871/15 "2023-12-01T11:07:53Z")

</div>

I have just added the example that was failing for me to the github project. The build issue will come later, that requires a more detailed description 🙂

---

<div class="post-metadata">

**Author:** ![fluidnumerics\_joe](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/fluidnumerics_joe/32/4360_2.png) [@fluidnumerics\_joe](https://fortran-lang.discourse.group/u/fluidnumerics_joe)\
**Post date:** [December 1, 2023, 9:50pm UTC](https://fortran-lang.discourse.group/t/feq-parse-updates-evaluation-with-arrays-now-supported/6871/16 "2023-12-01T21:50:30Z")

</div>

Thanks @vmagnin, @ivanpribec , and @arjen for the feedback. Because of your responses, I now have tests for gfortran-9 through gfortran-12 and the Intel OneAPI compilers set up, with testing on Ubuntu and Windows (gfortran only here at the moment). Checks on memory usage are also done with valgrind for debug builds.

Since the original post, we now have rank 1 through rank 4 arrays up and running. Additionally, we have a few new issues open to resolve bugs with the intel compilers and to look into some new features (e.g. overridable functions). Aside from addressing the bugs, I’m planning on finishing out the  
year on this repository with some documentation for developers and users, before tackling new features.

If you end up using this repository in another project, feel free to add a link back to your project in the feq-parse `README` . Also, give the repository a ⭐ on Github if you like it!

---

<div class="post-metadata">

**Author:** ![Arjen](https://avatars.discourse-cdn.com/v4/letter/a/b9bd4f/32.png) [@Arjen](https://fortran-lang.discourse.group/u/Arjen)\
**Post date:** [December 2, 2023, 2:12pm UTC](https://fortran-lang.discourse.group/t/feq-parse-updates-evaluation-with-arrays-now-supported/6871/17 "2023-12-02T14:12:35Z")

</div>

I have described the build issues I had yesterday in a new ticket. By the looks of them solving ought to be easy. Note: I used yesterday’s version.

---

<div class="post-metadata">

**Author:** ![gronki](https://avatars.discourse-cdn.com/v4/letter/g/a88e4f/32.png) [@gronki](https://fortran-lang.discourse.group/u/gronki)\
**Post date:** [December 5, 2023, 3:46pm UTC](https://fortran-lang.discourse.group/t/feq-parse-updates-evaluation-with-arrays-now-supported/6871/18 "2023-12-05T15:46:01Z")

</div>

That is a super cool project. I am writing a scripting interpreted language myself, fully in Fortran, for astrophysical image processing. This library will be PERFECT for evaluation of arbitrary transformation on images. Amazing work!

---

<div class="post-metadata">

**Author:** ![fluidnumerics\_joe](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/fluidnumerics_joe/32/4360_2.png) [@fluidnumerics\_joe](https://fortran-lang.discourse.group/u/fluidnumerics_joe)\
**Post date:** [December 5, 2023, 3:58pm UTC](https://fortran-lang.discourse.group/t/feq-parse-updates-evaluation-with-arrays-now-supported/6871/19 "2023-12-05T15:58:13Z")

</div>

Glad you’ll find it useful! Let me know if you need any assistance - you can either open a new discussion about your project on the discourse or open an issue at the feq-parse repository!

---

<div class="post-metadata">

**Author:** ![fluidnumerics\_joe](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/fluidnumerics_joe/32/4360_2.png) [@fluidnumerics\_joe](https://fortran-lang.discourse.group/u/fluidnumerics_joe)\
**Post date:** [December 6, 2023, 8:12pm UTC](https://fortran-lang.discourse.group/t/feq-parse-updates-evaluation-with-arrays-now-supported/6871/20 "2023-12-06T20:12:34Z")

</div>

Thanks again to everyone for the feedback. The master branch now has fixes in place for ifort and ifx compilers as well as builds for Windows with Visual Studio and CMake. I’ve currently got an issue open for using the `ifx` compiler with `fpm` (even though it works fine with CMake); this issue is summarized here [fpm test with `ifx` compiler fails · Issue #16 · FluidNumerics/feq-parse · GitHub](https://github.com/FluidNumerics/feq-parse/issues/16)

[Next page](https://fortran-lang.discourse.group/t/feq-parse-updates-evaluation-with-arrays-now-supported/6871.md?page=2)
