5 ms·
Any Fortran folks around ? Since old Fortran does not have function pointers I used to wonder how does one write gradient descent routine for a user defined fu
by srean 9mo ago
Any Fortran folks around ?
Since old Fortran does not have function pointers I used to wonder how does one write gradient descent routine for a user defined function in Fortran.
In other languages, one typically passes the user defined function and it's gradient to the routine as callbacks, so that the routine can call them at will.
It was a moment of great amusement and joy (grinning like a silly kid) when I learned how Fortran did it. It was through a pared down form of a coroutine. Inversion of control.
The gradient descent routine would effectively suspend and 'return' with a flag indicating that it needs the user defined function computed, or the gradient function computed.
These are computed outside and then the routine is called again with these recently computed values. At this point it resumes from where it had yielded. Pretty neat.
The routine's return value indicated whether it is done, or that it is suspended and expects to be called again to resume.
Now I don't remember if the suspended state was stored transparently by the run time, or explicitly in the arguments of the routine (pass by reference, I think), or whether the local, routine specific 'program counter' was managed explicitly or transparently by the compiler and run time.
- throwaway81523 9mo agoFortran has always had function pointers though they were called something different, and could only be used in limited contexts. But look at any numerical integration or root finding library. You just pass the function name in as a parameter to another function.
- lixiasky 9mo agoThat is a fascinating comparison! History really does rhyme. What you described—suspending with a flag and resuming with new values—is surprisingly similar to how the C++20 compiler transforms coroutines into a state machine under the hood. In tiny_coro, the promise_type essentially manages that "inversion of control" you mentioned, but hides the manual state management behind the co_await syntax. It's really cool to see that these fundamental patterns for "stopping and resuming" computation have existed for so long, just in different forms.
- throwaway81523 9mo agoAlso look at Protothreads :)
- lixiasky 9mo agoOh absolutely! Adam Dunkels' work is legendary. It's kind of poetic that Protothreads achieved stackless concurrency via C preprocessor macros and Duff's device tricks, and now years later, C++20 finally baked that exact same "state machine via switch-case" logic directly into the compiler. Same spirit, just less macro magic! :)
- srean 9mo agoSimon Tatham and Tom Duff too. https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
- lixiasky 9mo agoThe legendary "Coroutines in C" article! Thanks for the reference—I learned a lot from his work. His use of macros to hide the switch statement is basically the spiritual ancestor of co_await. It is wild to think that C++20 essentially standardized that exact pattern, just moving the "state machine generation" from the preprocessor hacks to the compiler itself.
- srean 9mo ago