- Um alte wissenschaftliche und technische Rechenressourcen in Form von Fortran-Numerikcode in den Browser zu bringen, ist ein WebAssembly-Kompilierungspfad nötig; webR verwendet dafür ein gepatchtes LLVM
flang-new f2c, LFortran, Dragonegg, Classic Flang und LLVM Flang haben jeweils Grenzen bei Unterstützung für modernes Fortran, Zielarchitekturen und Wartbarkeit; eine einfache Standardlösung gibt es daher noch nicht- LLVM Flang unterstützt das Target
wasm32-unknown-emscriptennicht direkt, sodassTargetWasm32ergänzt werden muss; beim Verknüpfen der Runtime verursacht der Unterschied in der Größe vonlongzwischen Host und Target Probleme - Kombiniert man das gepatchte
flang-new, Emscripten und statische Bibliotheken der Fortran-Runtime, lassen sich Fortran-Subroutinen aus C oder JavaScript aufrufen und auchPRINT,ALLOCATEsowieCHARACTER-Argumente verarbeiten - Die Referenzimplementierungen von BLAS 3.12.0 und LAPACK 3.12.0 wurden als statische WebAssembly-Bibliotheken gebaut, um Demos für Handschrifterkennung von Ziffern und Polynominterpolation im Browser auszuführen
Bestehenden Fortran-Numerikcode in den Browser bringen
- Fortran ist eine alte Sprache aus dem Jahr 1957, wurde aber lange in wissenschaftlichen und technischen Berechnungen eingesetzt; modernes Fortran hat die meisten Beschränkungen des festen Formats von Fortran 77 hinter sich gelassen
- Ziel ist es, moderne Fortran-Routinen nach WebAssembly zu kompilieren, im Browser auszuführen, numerische Argumente entgegenzunehmen, BLAS- und LAPACK-Routinen zu berechnen und anschließend Ergebnisse zurückzugeben oder auf der Konsole auszugeben
- Dieser Ansatz ermöglicht es, höhere Programmierumgebungen wie SciPy oder R, die auf BLAS und LAPACK angewiesen sind, ins Web zu bringen
- Statt numerische Routinen in JavaScript oder Rust neu zu schreiben, lassen sich bereits validierte Fortran-basierte Werkzeuge und Bibliotheken nutzen
- Das webR-Projekt kompiliert Fortran-Code mit einem gepatchten LLVM
flang-new-Compiler nach WebAssembly - Der aktuelle Ansatz beruht auf Hacks; ohne Hilfe erfahrenerer Compiler-Entwickler ist es schwierig, die Änderungen zu LLVM beizutragen
Stand der Werkzeuge für Fortran→WebAssembly
- Stand 2024 gibt es mehrere Werkzeuge und Toolchains, aber noch keine einfache Lösung mit vollständigem Funktionsumfang
-
f2cf2cwandelt Fortran 77 in C-Code um, den Emscripten anschließend nach WebAssembly kompilieren kann- Pyodide nutzt diesen Ansatz beim Kompilieren von Python-Paketen, die Fortran-Code enthalten
- Auch in der Pyodide-Roadmap wird dieser Ansatz als „funktioniert nicht gut“ bewertet
- Für modernen Fortran-Code passt er nicht, und selbst nach der Umwandlung sind gravierende Fehler und umfangreiche Patches nötig
-
LFortran
- LFortran hat in den letzten Jahren deutlich an Funktionsumfang gewonnen und kann direkt nach WebAssembly kompilieren
- Da es sich noch in der Alpha-Phase befindet, weisen die Entwickler darauf hin, dass beim Kompilieren realer Codebasen mit Problemen zu rechnen ist
- Einige Projekte wie MINPACK lassen sich kompilieren, doch da nicht die vollständige Fortran-Spezifikation unterstützt wird, können größere Projekte scheitern
- Entwicklungsziel ist die vollständige Unterstützung von Fortran 2018; eine auffällige Funktion ist ein interaktives Fortran-REPL ähnlich Jupyter
-
Dragonegg
- Dragonegg ist ein GCC-Plugin, das GCC-Frontends verwendet und LLVM IR ausgibt
- Über das LLVM-Backend kann WebAssembly-Ausgabe erzeugt werden; so kompilierte webR anfänglich Fortran-Quellen nach WebAssembly
- Die neuesten unterstützten Versionen sind
gcc-4.8undllvm-3.3, sodass sehr alte GCC- und LLVM-Versionen nötig sind - Die meisten Nutzer brauchen eine VM oder einen Docker-Container, und das von Dragonegg ausgegebene LLVM IR muss für die WebAssembly-Ausgabe zusätzlich nachbearbeitet werden
- Im Jahr 2020 war dies praktisch die einzige realistische Methode, um Fortran-Code nach WebAssembly zu kompilieren
-
Classic Flang
- Classic Flang ist ein auf dem als Open Source veröffentlichten PGI/NVIDIA
pgfortranbasierender Fortran-Compiler für LLVM - Da er keine 32-Bit-Ausgabe unterstützt, kann er nicht für das Target
wasm32verwendet werden - Firefox, Chrome und Node unterstützen zum Zeitpunkt der Erstellung
wasm64, allerdings hinter Feature-Flags - Auch die Projektdokumentation weist darauf hin, dass es möglicherweise keine gute Idee ist, Classic Flang für neue Projekte zu wählen
- Classic Flang ist ein auf dem als Open Source veröffentlichten PGI/NVIDIA
-
LLVM Flang
- LLVM Flang ist ein Projekt, das ein Fortran-Frontend für LLVM von Grund auf neu implementiert; seit LLVM 11 ist es Teil des LLVM-Projekts
- Es gilt zwar noch nicht als produktionsreif, doch die Pre-Production-Version von
flang-newist inzwischen für das Kompilieren realen Fortran-Codes recht brauchbar - Im Ausgangszustand kann es keine WebAssembly-Ausgabe erzeugen
- Dank des modularen Designs von LLVM lassen sich das Flang-Frontend und das LLVM-WebAssembly-Backend gemeinsam nutzen
- Auch 2020 war das schon möglich, erforderte aber größere LLVM-Patches, das Einschleusen eigener Mathematik-Routinen und einen mehrstufigen Kompilierungsprozess
- Heute lässt sich dank der Entwicklung des
flang-new-Frontends mit nur kleinen Änderungen am LLVM-Quellcode ein Compiler für Fortran→WebAssembly erstellen
LLVM Flang für WebAssembly bauen
- Ein über den Paketmanager installiertes LLVM enthält möglicherweise kein
flang-new-Binary- Beispielsweise findet man bei LLVM v17.0.6 aus macOS Homebrew den Befehl
flang-newnicht
- Beispielsweise findet man bei LLVM v17.0.6 aus macOS Homebrew den Befehl
- Da der LLVM-Flang-Quellcode geändert werden muss, wird LLVM v18.1.1 aus dem Quellcode selbst gebaut
- Die CMake-Konfiguration setzt das Standard-Target-Triple auf
wasm32-unknown-emscriptenund aktiviert das TargetWebAssemblysowie die Projekteclang;flang;mlir - Nach Abschluss des Builds lässt sich mit
build/bin/flang-new --versionFolgendes prüfen- Version:
flang-new version 18.1.1 - Target:
wasm32-unknown-emscripten - Thread-Modell:
posix
- Version:
Erstes Problem: Target wasm32 nicht implementiert
- Kompiliert man die einfache Fortran-Subroutine
foo.f08mitflang-new, tritt folgender Fehler aufnot yet implemented: target not implemented
- Ursache ist, dass das Target-Triple
wasm32-unknown-emscripteninflang-newnoch nicht implementiert ist - Die Lösung ist ein Patch, der in
flang/lib/Optimizer/CodeGen/Target.cppdie Target-Eigenschaften vonTargetWasm32ergänzt- Die Standardbreite wird auf 32 gesetzt
- Das Marshalling, das komplexe Argumente und Rückgabetypen in LLVM-Typen auf WebAssembly-Seite umwandelt, wird definiert
- Im Zweig
llvm::Triple::ArchType::wasm32wirdTargetWasm32angebunden
- Nach dem Patch und erneutem Build wird die Fortran-Quelle zu einem WebAssembly-Objekt kompiliert
- Ergebnis von
file foo.o:WebAssembly (wasm) binary module version 0x1 (MVP) - In
llvm-nm foo.oist das Symbolfoo_sichtbar
- Ergebnis von
Fortran-Subroutinen aus C und JavaScript aufrufen
- Fortran-Routinen übergeben Argumente üblicherweise per Referenz, und mit
INTENT()lässt sich deklarieren, wie Argumente verwendet werden - Die beispielhafte Fortran-Subroutine
foonimmt die Integer-Argumentex,yundzentgegen und führtz = x + yaus - Führt man in einem nativen Build
gfortran -c foo.f08 -o foo.oaus, kann der Symbolname wiefoo_einen angehängten Unterstrich erhalten - Beim Aufruf aus C deklariert man das externe Symbol etwa als
extern void foo_(int*, int*, int*);und übergibt die Argumente per Adresse - In WebAssembly kann das mit
flang-newerstelltefoo.oper Emscripten mit C-Code verknüpft werdenemcc main.c foo.o -o main.js- Ausgabe von
node main.js:1 + 1 = 2
-
Direkter Aufruf aus JavaScript
- Fortran-Subroutinen lassen sich auch ohne C-Code direkt aus JavaScript aufrufen
- Beim Emscripten-Link-Schritt werden
_foo_,_mallocund_freeexportiert emcc foo.o -sEXPORTED_FUNCTIONS=_foo_,_malloc,_free -o foo.js- JavaScript reserviert mit
Module._malloc()Speicher für Integer-Werte, schreibt Werte inModule.HEAPU32und ruft anschließendModule._foo_(x, y, z)auf - Das Ausführungsergebnis sieht so aus
x = 123y = 456x + y = 579- Im Browser lassen sich
foo.jsundstandalone.jsaus HTML laden, um dasselbe Ergebnis in der JavaScript-Konsole zu sehen
Zweites Problem: Fortran-Runtime-Bibliothek
- Baut man eine Fortran-Subroutine mit
PRINT *, "Hello, World!", tritt beim Linken ein Fehler wegen fehlender Runtime-Symbole auf_FortranAioBeginExternalListOutput_FortranAioOutputAscii_FortranAioEndIoStatement
- Ursache ist, dass die LLVM-Fortran-Runtime-Bibliothek noch nicht für WebAssembly kompiliert wurde
- Die Runtime-Bibliothek ist in C++ im Verzeichnis
llvm-project/flang/runtimedes LLVM-Quellbaums geschrieben - Baut man die Runtime-Quellen mit
em++undemaraus Emscripten, kann man die statische Bibliothekbuild/flang/runtime/libFortranRuntime.aerstellen - Verlinkt man diese Bibliothek, schreitet der Build von
Hello, World!fort, zunächst erscheinen jedoch Warnungen zu nicht übereinstimmenden Funktionssignaturen
Drittes Problem: Unterschiedliche long-Größe bei Host und Target
- Beim Verknüpfen von
hello.omit der Fortran-Runtime-Bibliothek erscheint eine Warnung wegen nicht übereinstimmender Signaturen für_FortranAioOutputAscii- Das Fortran-Objekt erwartet
(i32, i32, i64) -> i32 - Die mit Emscripten gebaute Runtime definiert
(i32, i32, i32) -> i32
- Das Fortran-Objekt erwartet
- WebAssembly verlangt, dass die Argument- und Rückgabetypen von Symbolen, die über mehrere Compilation Units hinweg definiert sind, konsistent sind
- Dieses Problem bleibt nicht bei einer Warnung; die Ausführung in Node scheitert mit
RuntimeError: unreachable - In LLVM Flangs
RTBuilder.hgibt es einen TODO-Kommentar, wonach die Verwendung vonsizeofbuild == host == targetvoraussetzt - Auf modernen 64-Bit-Unix-artigen Hosts ist
sizeof(long)8 Byte, beim Targetwasm32-unknown-emscriptenmuss es jedoch 4 Byte sein - Beim Übergeben von Argumenten des Fortran-Typs
CHARACTERan Funktionen oder Subroutinen kann ein verstecktes Argument zur Zeichenkettenlänge hinzugefügt werden - In der Fortran-Runtime-Bibliothek ist dieses Längenargument als
size_tdeklariert und wird über einetypedef-Kette zuunsigned long - Dieser Größenunterschied beim versteckten Argument verursacht die Abweichung zwischen
i64undi32
Vorläufiger Patch: 4-Byte-Werte erzwingen
- Die ideale Lösung wäre, dass
flang-newbeim Cross-Compiling unabhängig vom Hosti32oderi64passend zur Target-Architektur und zum Datenmodell ausgibt - Derzeit wird ein Patch verwendet, der die Größe von
longfest auf 4 Byte fürwasm32und Emscripten setzt - Der Patch besteht aus zwei Teilen
- In
RTBuilder.hwerden die Modelltypen fürlongundunsigned longnicht aus8 * sizeof(...), sondern erzwungen als8 * 4gesetzt - In
CodeGen.cppwerden Argumente fürmalloc()-Aufrufe als 32-Bit- statt 64-Bit-Integer erzeugt, und die Allokationsgröße wird nachi32gecastet
- In
- Diese Änderung behebt auch die in Fortran 90 eingeführte dynamische Allokation mit
ALLOCATE() - Nach dem erneuten Build lassen sich
hello.f08undhello.cohne Warnungen mit der Runtime-Bibliothek verknüpfen, und Node gibt Folgendes ausHello, World!
BLAS nach WebAssembly bauen
- BLAS ist eine Sammlung von Low-Level-Routinen für gängige Operationen der linearen Algebra, etwa Matrix-Vektor-Multiplikation
- Die ursprünglichen BLAS-Routinen wurden 1979 veröffentlicht und sind de facto Standard im Bereich numerischer Berechnungen
- Die Referenzimplementierung BLAS 3.12.0 ist in Fortran 90 geschrieben und bei netlib erhältlich
- In
make.incwerden für den Build folgende Werkzeuge angegebenFC = ../build/bin/flang-newFFLAGS = -O2AR = emarRANLIB = emranlib
- Als Build-Ergebnis entsteht die statische Bibliothek
blas_LINUX.a - Die beispielhafte Fortran-Routine
barruft die BLAS-Level-2-RoutineZGEMV()auf ZGEMV()führt komplexwertige Matrix-Vektor-Operationen aus; das Beispiel verwendet Argumente vom TypCOMPLEX(KIND=8)sowie dasCHARACTER-Konfigurationsargument'N'- Ein C-Programm erstellt komplexe Arrays, übergibt sie an die Fortran-Routine und gibt anschließend das Ergebnis aus
- Das Ergebnis der Ausführung in Node lautet wie folgt
Y[0]: 23.000000 + 6.000000iY[1]: 18.000000 + 10.000000iY[2]: 6.000000 + 16.000000i
- Dieses Ergebnis bestätigt, dass aus Fortran-90-Quellen kompilierte BLAS-Routinen unter WebAssembly laufen
Browser-Beispiel: Klassifikator für handgeschriebene Ziffern
- Die Demo klassifiziert von Hand gezeichnete Ziffern von 0 bis 9 mit einem künstlichen neuronalen Netz vom Typ Multilayer Perceptron (MLP)
- Nutzer können mit Maus oder Touchscreen eine Ziffer zeichnen; die vom Netzwerk vorhergesagten relativen Wahrscheinlichkeiten werden im Diagramm rechts angezeigt
- Die Modellgewichte wurden mit Python vortrainiert, die Klassifikation erfolgt zur Laufzeit jedoch im Browser mit JavaScript und WebAssembly
- Der MLP-Klassifikationsprozess besteht im Kern aus wiederholten Matrix-Vektor-Additionen und -Multiplikationen
- Die rechenintensiven Teile übernimmt eine Fortran-Subroutine, die die BLAS-Level-2-Routine
DGEMV()verwendet
LAPACK nach WebAssembly bauen
- LAPACK ist eine Softwarebibliothek zur numerischen Lösung von Problemen der linearen Algebra und baut auf BLAS auf
- Die Referenzimplementierung LAPACK 3.12.0 wird von netlib bereitgestellt und unter einer modifizierten BSD-Lizenz vertrieben
- Nach dem Kopieren von
make.inc.examplenachmake.incwerden folgende Einstellungen geändertFCwird auf den vollständigen Pfad des gebautenflang-newgesetztFFLAGS = -O2AR = emarRANLIB = emranlibTIMER = INT_CPU_TIME
- Mit dem Befehl
make libwird die statische WebAssembly-Bibliothekliblapack.aerzeugt - Anschließend lassen sich LAPACK-Routinen ähnlich wie im BLAS-Beispiel aufrufen
Browser-Beispiel: Polynominterpolation mit linearer Algebra
- Die Demo findet ein Interpolationspolynom für eine Menge von Punkten und zeigt, dass LAPACK-Routinen im Browser laufen
- Wenn Nutzer durch Klicken in das Diagramm einen neuen Punkt hinzufügen, wird ein Interpolationspolynom gesucht, das durch alle Punkte verläuft
- Das Verfahren nutzt die Vandermonde-Methode
- Das dabei entstehende lineare Gleichungssystem wird numerisch mit der LAPACK-Routine
DGELS()gelöst - Für
nDatenpunkte lässt sich stets ein Polynom vom Gradn-1finden, das alle Punkte exakt enthält - Wenn
ngrößer wird, kann zwischen benachbarten Datenpunkten das Runge-Phänomen auftreten, bei dem das Polynom stark oszilliert; dies lässt sich durch Spline-Interpolation vermeiden
Offene Aufgaben und bereitgestellte Werkzeuge
- Mit einem gepatchten LLVM Flang lässt sich moderner Fortran-Code zu WebAssembly-Objekten kompilieren
- Der Vorteil dieses Ansatzes besteht darin, vorhandene Fortran-Werkzeuge und -Bibliotheken zu nutzen, statt numerische Algorithmen für das Web in JavaScript neu zu schreiben
- Wenn
flang-newWebAssembly offiziell unterstützt, sinkt der Aufwand, für webR und R-Pakete einen LLVM-Fork zu pflegen - Derzeit ist ein besserer Weg nötig, um LLVM Flang und Cross-Compilation-Probleme für alle Targets korrekt zu beheben
- Für Nutzer, die LLVM Flang nicht selbst bauen können oder wollen, steht in der GitHub Container Registry ein Docker-Container mit gepatchten LLVM-Flang-Binaries bereit
1 Kommentare
Hacker-News-Kommentare
Um etwas Kontext zu geben: Diese Fortran-Erkundung ist Teil von Georges hervorragender Arbeit an WebR, mit der er R im Browser zum Laufen bringen will.
Im R-Quellcode steckt ziemlich viel Fortran-Code, und soweit ich weiß, kompilierte WebR Fortran ursprünglich zuerst mit f2c nach C und dann dieses C nach wasm.
Dank des LLVM-Flang-Patches lässt sich WebR nun mit einem echten Fortran-Compiler bauen.
George hat es in seinem Blogpost nicht direkt gesagt, aber er hat erwähnt, dass er hofft, Flang werde diesen Patch übernehmen oder auf bessere Weise implementieren.
Dann müsste kein separater Patch mehr gepflegt werden, und ein unverändertes Flang könnte nach wasm kompilieren, was auch anderen Projekten zugutekäme, die Fortran verwenden.
https://docs.r-wasm.org/webr/latest/
Allerdings konzentriere ich mich auf die Arbeiten, die nötig sind, um Nvidias Fortran-Produktentwicklung abzuschließen, daher bleibt mir für solche Arbeiten keine Zeit.
Vor 20 Jahren habe ich bei Xilinx an der FORTRAN-Kompilierung gearbeitet, und das Einzige, woran ich mich erinnere, ist, dass es in der Header-Datei f2c.h eine Definition von
barfgab./* f2c.h -- Standard Fortran to C header file //* barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed."(https://www.netlib.org/clapack/f2c.h)
Ich finde es wirklich gut, als Erkläransatz das einfachste nicht-triviale Beispiel zu verwenden.
Der Artikel basiert auf dem konkreten Problem „eine BLAS-Funktion aus JavaScript aufrufen“, dadurch hatte ich das Gefühl, viel gelernt zu haben; ein großartiger Beitrag.
[1] https://en.m.wikipedia.org/wiki/The_Theoretical_Minimum
Ich weiß nicht, ob ich beeindruckt oder entsetzt sein soll, wahrscheinlich beides.
Beim Bauen von f18 empfehle ich, die aktuellsten Quellen aus llvm-project/main zu verwenden.
Das Projekt bewegt sich schnell; es ist Zeitverschwendung, Probleme zu debuggen, die schon behoben sind, oder Funktionen zu verpassen, die bereits implementiert wurden.
Geht es darum, am WebAssembly-Port zu arbeiten und ihn an den Punkt zu bringen, an dem der Zwischencode bis hin zu Fortran funktioniert?
Mit WebAssembly-Entwicklung kenne ich mich nicht gut aus.
Gibt es aus Verbrauchersicht etwas, das WebAssembly schon heute bietet? Oder ist es eher Grundlagenarbeit für eine Zukunft, in der Programme wirklich portabel werden?
Ich habe gehört, dass die WebAssembly-Vorrichtung Zugriffsbeschränkungen etwa auf Netzwerk oder Dateien erleichtert, weiß aber nicht, ob das Theorie ist oder bereits implementiert wurde.
Der zentrale Unterschied ist, dass Wasm selbst weder eine Standardbibliothek hat noch Ein-/Ausgabefunktionen bereitstellt.
Deshalb kann der Host, also derjenige, der die VM baut, Funktionen bereitstellen, die ein Wasm-Binary importieren kann; das Wasm-Binary kann ausschließlich über diese Funktionen auf die Außenwelt zugreifen.
Ein weiterer Vorteil ist, dass das Binärformat nicht proprietär ist und eine Spezifikation hat, sodass jeder eine Wasm-VM implementieren kann.
Allerdings ist der Stand derzeit noch nicht wirklich gut; es ist noch sehr früh, viele neue Funktionen werden in Gruppen ähnlich dem W3C standardisiert, und der Prozess ist sehr langsam.
Es gibt auch Möglichkeiten, es auf die meisten Ziele auszuliefern oder dafür zu cross-kompilieren.
Das ist ähnlich wie bei der Frage, ob der Computer eine ARM- oder x86-CPU hat: In der Regel weiß man es nicht und kümmert sich auch nicht groß darum.
Wenn einem also Details wie „läuft es als nativer Code oder auf einer VM wie JVM, .NET oder WASM“ egal sind, ist es schwer zu sagen, was es gegenüber anderen Lösungen zusätzlich bietet.
Meist fallen nur die schlechten Beispiele auf, und daraus werden dann Memes wie „alle Electron-Programme sind aufgeblähte, ressourcenfressende Monster, und jede native App ist automatisch ein Wunderwerk effizienter Softwaretechnik“.
Schade, wenn ich den Fortran-78-Code aufbewahrt hätte, den ich 1981/82 geschrieben habe, hätte ich testen können, ob er hier läuft.
Es war ein Quellcode-Formatter für die Programmiersprache Jovial, und eigentlich war das nichts, was man in Fortran machen sollte, aber damals war das die einzige Option.
Gibt es ein halbwegs production-reifes Linear-Algebra-Ökosystem für JavaScript?
Wenn ich suche, finde ich meist nur JavaScript-Ports bekannter Bibliotheken, die etwa 10 Jahre alt sind, zum Beispiel Ports über emscripten; ich frage mich, ob ich etwas übersehe.
Es ist seltsam, dass LFortran nicht ausführlicher behandelt wird
Es gibt auch ein hervorragendes und beeindruckendes WASM-Beispiel, das online läuft
https://dev.lfortran.org/
2020 fehlten noch viele Funktionen, und es wurde nur eine sehr kleine Teilmenge von Fortran unterstützt; inzwischen unterstützt er aber einen deutlich größeren Teil der Sprachfeatures und kann recht viel Fortran-Code kompilieren
Auch die native Kompilierung nach WebAssembly ist möglich
Allerdings gibt es bei der Nutzung von LFortran noch raue Kanten; die Entwickler weisen darauf hin, dass das Projekt derzeit als Alpha gilt und beim Kompilieren von echtem Code Probleme auftreten können
Einige Projekte wie MINPACK lassen sich erfolgreich kompilieren, doch da die vollständige Fortran-Spezifikation noch nicht unterstützt wird, lassen sich viele größere Projekte weiterhin nicht kompilieren
Die LFortran-Entwickler zielen auf vollständige Unterstützung von Fortran 2018 ab, und ein auffälliges Feature ist ein interaktives Fortran-REPL wie in Jupyter
Mit ein paar weiteren Jahren Entwicklung dürfte es eine hervorragende Option zum Kompilieren von Fortran-Code für WebAssembly werden
Außerdem wird auf die LFortran-Demo unter https://dev.lfortran.org verwiesen; sie ist sehr beeindruckend, aber mein erster Versuch,
x * 2inx * 3zu ändern, wurde vom aktuellen Codegenerator nicht unterstütztEs gibt auch Fortran auf .NET und Java
https://www.silverfrost.com/14/ftn95/ftn95_fortran_95_for_microsoft_dotnet_features.aspx
https://dl.acm.org/doi/10.1145/376656.376833
Als ich an https://medium.com/@tomasreimers/compiling-tensorflow-for-the-browser-f3387b8e1e1c gearbeitet habe, war ich wirklich froh, dass TensorFlow Eigen nutzt und nicht die beliebten, in Fortran geschriebenen Mathematikbibliotheken BLAS/Lapack
Sonst wäre es deutlich mehr Arbeit gewesen