**Summary**

For those who are new to 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. 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.

```
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

```
./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.

```
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** )

```
./array_with_array_eval
runtime : 0.270846009 s
```