User defined functions in constant expressions

@mfurquan ,

I strongly encourage you to develop your ideas, collaborate with the Fortran Community as you deem appropriate, research options/solutions, and develop proposal(s) toward this. You may know of GitHub Fortran proposals site, you may want to consider at site for this:

Constexpr as much as possible” or in other words, utilize as much compile-time computing as viable is a mantra that’s increasingly becoming important in many modern codes based on C++17 (and later revisions) toward scientific and technical computing in industry, especially in process simulations and modeling.

Improved constexpr in C++17 is particularly valuable when one needs to construct large named constants arrays for use in simulations based on other constants (e.g., coefficients in engineering correlations, results from prior simulation runs, results from first-principles models to be applied in reduced-order models, etc.). These are all use cases that are rather similar to the one you show well with the derivatives of Lagrange polynomials.

Sometime ago a team I was working with had to reuse certain case-based logic to construct some data in engineering calculations and they wanted to set it all up just as the libraries were loaded (c.f. Windows DLLs). It was a real pain in Fortran but a breeze with C++17 (supported well by Microsoft C++ processor). I even put together a MWE, ostensibly silly, for what they were trying to do having removed all their business logic of course:

// Example #  : MWE-9.F202Y.003
// Author     : FortranFan
// Reference  : CONSTEXPR precedures
//
// Description:
// An example in C++17 of constexpr functions that help with
// case-based logic to generate constant arrays at compile-time

#include <array>
#include <iostream>
using namespace std;

// Some base data
constexpr int N = 3;
constexpr std::array<int, N> vals = { 1, 2, 3 };
constexpr std::array<double, N> base_data = { 1.0, -2.0, 3.0 };

// Calculation from base data
constexpr int M = 5;
constexpr std::array<int, M> idx = { vals[2], vals[0], vals[1], vals[0], vals[1] };
// Some user function 1 
constexpr double user_func1(int n) {
   switch ( idx[n-1] )
   {
       case vals[0] : return base_data[0] + 2.0;   break;
       case vals[1] : return base_data[1] - base_data[2]; break;
       case vals[2] : return 0.0;  break;
       default      : return -1.0; break;
   }
}
// Load data at compile-time using user function 2
constexpr std::array<double, M> user_func2{ user_func1(1), user_func1(2), user_func1(3),
   user_func1(4), user_func1(5) };

int main() {
   for (int i = 0; i < M; i++) {
      std::cout << "user_func2[" << i << "] = " << user_func2[i] << "\n";
   }
   return 0;
}

C:\temp>cl /EHsc ce.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.27.29112 for x64
Copyright (C) Microsoft Corporation. All rights reserved.

ce.cpp
Microsoft (R) Incremental Linker Version 14.27.29112.0
Copyright (C) Microsoft Corporation. All rights reserved.

/out:ce.exe
ce.obj

C:\temp>ce.exe
user_func2[0] = 0
user_func2[1] = 3
user_func2[2] = -5
user_func2[3] = 3
user_func2[4] = -5

C:\temp>

The ability to have nonintrinsic i.e., user-defined functions that are of, say, CONSTEXPR prefix-spec in Fortran will be entirely consistent, in my opinion, with the evolution path of Fortran with PURE/ELEMENTAL procedures in Fortran 95 to SIMPLE procedures in Fortran 202X. Most of the semantics are already there in Fortran, I personally think it merely needs some adjustments to the language standard (tightening of requirements in some places, some loosening elsewhere).

So my suggestion to the Fortran committee and the Community will be to consider a new procedure prefix-spec CONSTEXPR that not only requires the procedure to be SIMPLE (the above-mentioned new Fortran 202X feature) but that each instruction in such a procedure either be constant expression or involve a CONSTEXPR procedure. Of course, the details are yet to be fully fleshed out.

The introduction of such a CONSTEXPR procedure in a future Fortran standard, say 202Y, will greatly enhance compile-time computing facilities in Fortran and I have no doubt that will be of great benefit in scientific and technical computing.

Kudos to you for bringing this up here.