Compare commits
No commits in common. "main" and "ancient_toolbox_easter_egg" have entirely different histories.
main
...
ancient_to
64
src/App.vue
64
src/App.vue
@ -1,12 +1,65 @@
|
|||||||
<template>
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
import {ref} from "vue";
|
||||||
|
|
||||||
|
const toolbar = ref<boolean>(false);
|
||||||
|
const canGoForward = ref<boolean>(false);
|
||||||
|
const canGoBack = ref<boolean>(false);
|
||||||
|
|
||||||
|
function activateToolbar() {
|
||||||
|
toolbar.value = !toolbar.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function goBack() {
|
||||||
|
canGoBack.value = window.history.length <= 1;
|
||||||
|
history.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
function goForward() {
|
||||||
|
canGoForward.value = window.history.length <= 1;
|
||||||
|
history.forward();
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
<div class="flex flex-col min-h-screen bg-var_background">
|
<div class="flex flex-col min-h-screen bg-var_background">
|
||||||
|
|
||||||
|
<div v-if="toolbar">
|
||||||
|
<div class="w-full py-small bg-ancient_highlight shadow-xl"></div>
|
||||||
|
<div class="w-full py-small bg-ancient_shadow"></div>
|
||||||
|
<div class="flex justify-center bg-ancient">
|
||||||
|
<div class="w-full max-w-screen-lg px-4">
|
||||||
|
<button @click="goBack" v-if="canGoBack">
|
||||||
|
<img src="/public/Icons/toolbar/Back.avif" width="32px" height="32px" class="mx-2" alt="Ancient looking back button">
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button @click="goBack" v-if="!canGoBack" disabled>
|
||||||
|
<img src="/public/Icons/toolbar/Back_Gray.avif" width="32px" height="32px" class="mx-2" alt="Ancient looking back button">
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button @click="goForward" v-if="canGoForward">
|
||||||
|
<img src="/public/Icons/toolbar/Forward.avif" width="32px" height="32px" class="mx-2" alt="Ancient looking forward button">
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button @click="goForward" v-if="!canGoForward" disabled>
|
||||||
|
<img src="/public/Icons/toolbar/Forward_Gray.avif" width="32px" height="32px" class="mx-2" alt="Ancient looking forward button">
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button><img src="/public/Icons/toolbar/Refresh.avif" width="20px" height="32px" class="mx-2" alt="Ancient looking forward button"></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="w-full py-small bg-ancient_highlight shadow-xl"></div>
|
||||||
|
<div class="w-full py-small bg-ancient_shadow"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<header class="flex justify-center">
|
<header class="flex justify-center">
|
||||||
<nav class="pt-10 text-2xl flex place-items-center">
|
<nav class="pt-10 text-2xl flex place-items-center">
|
||||||
<RouterLink class="mx-1" to="/">Home</RouterLink>
|
<RouterLink class="mx-1" to="/">Home</RouterLink> |
|
||||||
<RouterLink class="mx-1" to="/C">C</RouterLink>
|
<RouterLink class="mx-1" to="/About">About</RouterLink> |
|
||||||
<RouterLink class="mx-1" to="/Fortran">Fortran</RouterLink>
|
<RouterLink class="mx-1" to="/Fortran">Fortran</RouterLink> |
|
||||||
<RouterLink class="mx-1" to="/About">About</RouterLink>
|
<RouterLink class="mx-1" to="/Pascal">Pascal</RouterLink> |
|
||||||
|
<RouterLink class="mx-1" to="/Lisp">Lisp</RouterLink>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
@ -18,6 +71,7 @@
|
|||||||
|
|
||||||
<footer class="flex justify-center pt-10 mt-10 pb-2">
|
<footer class="flex justify-center pt-10 mt-10 pb-2">
|
||||||
<h5>Author: Still under construction</h5>
|
<h5>Author: Still under construction</h5>
|
||||||
|
<button @click="activateToolbar">Time travel</button>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1,62 +1,71 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|
||||||
import Paragraph from "./tags/Paragraph.vue";
|
|
||||||
import PageStart from "./tags/PageStart.vue";
|
|
||||||
import CodeTag from "./tags/CodeTag.vue";
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<page-start>About This Page</page-start>
|
<div>
|
||||||
|
<h1 class="text-3xl">About This Page</h1>
|
||||||
<paragraph>This page is about ancient (before the year 2000) programming languages, like Fortran and C. This page is mostly
|
<hr>
|
||||||
|
<p>This page is about ancient (before the year 2000) programming languages, like Fortran and C. This page is mostly
|
||||||
about showing how it was done before fancy build tools and syntax were a thing. It also serves a purpose of a
|
about showing how it was done before fancy build tools and syntax were a thing. It also serves a purpose of a
|
||||||
showing, with examples, how to not only set up the programming environments, but also the whole workflow from
|
showing, with examples, how to not only set up the programming environments, but also the whole workflow from
|
||||||
prototype to production.<br><br>
|
prototype to production.</p>
|
||||||
|
<br>
|
||||||
|
|
||||||
This whole idea started when I made my first "serious" blog, <a class="underline" href="https://rbwr.dk">rbwr.dk</a>, but it didn't
|
<p>This whole idea started when I made my first "serious" blog, <a class="underline" href="https://rbwr.dk">rbwr.dk</a>, but it didn't
|
||||||
feel like quite the "correct" place to put it. So the idea was shelved for a time... Until recently, when I picked
|
feel like quite the "correct" place to put it. So the idea was shelved for a time... Until recently, when I picked
|
||||||
up a project in Fortran. Yep, Fortran. I had gotten bored, and wanted to challenge myself. And I thought, that if
|
up a project in Fortran. Yep, Fortran. I had gotten bored, and wanted to challenge myself. And I thought, that if
|
||||||
I'm going to learn the language, I might as well put blood, sweat and tears into formulating and showcasing how
|
I'm going to learn the language, I might as well put blood, sweat and tears into formulating and showcasing how
|
||||||
it's done (correctly).<br><br>
|
it's done (correctly).</p>
|
||||||
|
<br>
|
||||||
|
|
||||||
I did initially want to try COBOL, but after looking at some examples, Fortran kind of looked more appealing lol.</paragraph>
|
<p>I did initially want to try COBOL, but after looking at some examples, Fortran kind of looked more appealing lol.</p>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
|
||||||
<h2 class="text-3xl">Who Am I?</h2>
|
<h1 class="text-3xl">Who Am I?</h1>
|
||||||
<hr>
|
<hr>
|
||||||
|
<p>My name is Rasmus Rasmussen (yes, that's my name), I live somewhere in the outskirts of Odense, Denmark, and I'm primarily
|
||||||
<paragraph>My name is Rasmus Rasmussen (yes, that's my name), I live somewhere in the outskirts of Odense, Denmark, and I'm primarily
|
|
||||||
a backend developer. But lately, I've started to like developing in vue3. With TypeScript, of cause. It's a nice
|
a backend developer. But lately, I've started to like developing in vue3. With TypeScript, of cause. It's a nice
|
||||||
chance of pace, and I often find myself wanting to experiment with different styling, as well as trying to
|
chance of pace, and I often find myself wanting to experiment with different styling, as well as trying to
|
||||||
optimize and minimize my bundles.<br><br>
|
optimize and minimize my bundles.</p>
|
||||||
|
<br>
|
||||||
|
|
||||||
I'm an educated datamatiker from UCL Erhvervsakademi og Professionshøjskole. (I have no idea what it's called
|
<p>I'm an educated datamatiker from UCL Erhvervsakademi og Professionshøjskole. (I have no idea what it's called
|
||||||
in English). Doing my study, I have primarily developed in C# and .NET, as well as ASPNET, JavaScript, SQL and
|
in English). Doing my study, I have primarily developed in C# and .NET, as well as ASPNET, JavaScript, SQL and
|
||||||
Umbraco. I have also set up multiple Linux unmanaged servers, together with Docker, that I use to host my websites
|
Umbraco. I have also set up multiple Linux unmanaged servers, together with Docker, that I use to host my websites
|
||||||
and web-application.<br><br>
|
and web-application.</p>
|
||||||
|
<br>
|
||||||
|
|
||||||
In my free time, I like to write blog posts about small, or sometimes big, project. It can be about anything,
|
<p>In my free time, I like to write blog posts about small, or sometimes big, project. It can be about anything,
|
||||||
really. The most important part is that I learn something. Like with my project
|
really. The most important part is that I learn something. Like with my project
|
||||||
<a class="underline" href="https://rbwr.dk/posts/setting_up_a_new_blazor_interactive_server_side_render_project/">where I was setting
|
<a class="underline" href="https://rbwr.dk/posts/setting_up_a_new_blazor_interactive_server_side_render_project/">where I was setting
|
||||||
up a Blazor Interactive SSR web app.</a> I learned quite a lot doing that project. For example how to handle file
|
up a Blazor Interactive SSR web app.</a> I learned quite a lot doing that project. For example how to handle file
|
||||||
upload, or some of the newer C# syntax, like the "Index from end expression" that looks like this: <code-tag>[^1]</code-tag><br><br>
|
upload, or some of the newer C# syntax, like the "Index from end expression" that looks like this <code>[^1]</code></p>
|
||||||
|
<br>
|
||||||
|
|
||||||
Another project I'm also quite proud of, is my own custom search engine. Or well, it was supposed to be a search
|
<p>Another project I'm also quite proud of, is my own custom search engine. Or well, it was supposed to be a search
|
||||||
engine, but ended up as a crawler, that collects statistics of various metrics, such as response codes, server
|
engine, but ended up as a crawler, that collects statistics of various metrics, such as response codes, server
|
||||||
type, Tls version, Etc. It's still running, as the IPv4 space is quite large. Some of the best aspects of the
|
type, Tls version, Etc. It's still running, as the IPv4 space is quite large. Some of the best aspects of the
|
||||||
projects, was that I learned how to optimally handle high amounts of threads (up to 256 threads) for the scanner
|
projects, was that I learned how to optimally handle high amounts of threads (up to 256 threads) for the scanner
|
||||||
to use, when finding websites on the internet.<br><br>
|
to use, when finding websites on the internet.</p>
|
||||||
|
<br>
|
||||||
|
|
||||||
A little more about me :) I like to bike. I have a normal, bog-standard bike cycle, that I like to bike large
|
<p>A little more about me :) I like to bike. I have a normal, bog-standard bike cycle, that I like to bike large
|
||||||
distances with. I try to aim at 80Km and as early as possible. Usually, when biking those distances, I aim to
|
distances with. I try to aim at 80Km and as early as possible. Usually, when biking those distances, I aim to
|
||||||
start the journey at 5 in the morning. It gives a good jolt of energy, when the morning fog hits. Plus, when
|
start the journey at 5 in the morning. It gives a good jolt of energy, when the morning fog hits. Plus, when
|
||||||
start that early on, you usually find some pretty cool scenes. Like this image I took at 5:30 in the morning, not
|
start that early on, you usually find some pretty cool scenes. Like this image I took at 5:30 in the morning, not
|
||||||
too far from my apartment.</paragraph>
|
too far from my apartment.</p>
|
||||||
|
<br>
|
||||||
|
|
||||||
<img src="/Images/avif/PXL_20230708_030149199_scaled.avif" alt="Meadow with fog." loading="lazy" decoding="async" width="1434" height="1080">
|
<img src="/public/Images/avif/PXL_20230708_030149199_scaled.avif" alt="Meadow with fog." loading="lazy" decoding="async" width="1434" height="1080">
|
||||||
<paragraph>Not bad huh? The things you see when everyone is asleep.</paragraph>
|
<p>Not bad huh? The things you see when everyone is asleep.</p>
|
||||||
|
<br>
|
||||||
|
|
||||||
<img src="/Images/avif/PXL_20230720_032828882_scaled.avif" alt="My humble bike." loading="lazy" decoding="async" width="1434" height="1080">
|
<img src="/public/Images/avif/PXL_20230720_032828882_scaled.avif" alt="My humble bike." loading="lazy" decoding="async" width="1434" height="1080">
|
||||||
<paragraph>And this is my humble bike. It has taken me many places, and it's still going strong. The odometer no longer works,
|
<p>And this is my humble bike. It has taken me many places, and it's still going strong. The odometer no longer works,
|
||||||
so I just use my FitBit Charge 5 instead. I've modeled and 3D printed the two orange bottle holders myself, on my
|
so I just use my FitBit Charge 5 instead. I've modeled and 3D printed the two orange bottle holders myself, on my
|
||||||
Original Prusa MK3S+.</paragraph>
|
Original Prusa MK3S+.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
@ -1,9 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
|
|
||||||
import PageStart from "../tags/PageStart.vue";
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<page-start>Hello World In Fortran 90</page-start>
|
|
||||||
|
|
||||||
</template>
|
|
@ -1,28 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
|
|
||||||
import Paragraph from "../tags/Paragraph.vue";
|
|
||||||
import PageStart from "../tags/PageStart.vue";
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<page-start>C</page-start>
|
|
||||||
|
|
||||||
<paragraph>C is one of those ancient languages that's still getting used to this very day. It's a language from
|
|
||||||
the year 1972, making it 53 years young as of 2025. It originated at Bell Labs, and was developed with the purpose of
|
|
||||||
creating utilities for Unix.<br><br>
|
|
||||||
|
|
||||||
In the 80s, C steadily became more and more accepted as the go-to language. Especially with kernel and driver code.
|
|
||||||
The Linux kernel is one such huge project written in almost purely C, although in recent times, the kernel is introducing
|
|
||||||
Rust code.
|
|
||||||
</paragraph>
|
|
||||||
|
|
||||||
<p>Table of contents:</p>
|
|
||||||
<ul>
|
|
||||||
<li><RouterLink to="/C/SetUp">> Set Up</RouterLink></li>
|
|
||||||
<li><RouterLink to="/C/SetUp">> Hello World</RouterLink></li>
|
|
||||||
</ul>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
@ -1,170 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
|
|
||||||
import PageStart from "../tags/PageStart.vue";
|
|
||||||
import Paragraph from "../tags/Paragraph.vue";
|
|
||||||
import CodeTag from "../tags/CodeTag.vue";
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<page-start>Setting Up The Environment</page-start>
|
|
||||||
|
|
||||||
<paragraph>
|
|
||||||
If you're familiar Fortran, then this guide will be quite easy for you. For C, there isn't really an "official"
|
|
||||||
compiler, but there are compilers that implement the standards of C. For this guide, we'll be using GCC. There are
|
|
||||||
other great compilers, such as clang.<br><br>
|
|
||||||
|
|
||||||
Just like with the <RouterLink to="/Fortran/SetUp">Fortran set up guide</RouterLink>, we'll be doing this on Fedora
|
|
||||||
Linux, but other distros, like Ubuntu, would work just as well.
|
|
||||||
</paragraph>
|
|
||||||
|
|
||||||
<p>For Fedora:</p>
|
|
||||||
<code-tag>$ sudo dnf install gcc</code-tag>
|
|
||||||
|
|
||||||
<p>For ubuntu:</p>
|
|
||||||
<code-tag>$ sudo apt install build-essential</code-tag>
|
|
||||||
|
|
||||||
<paragraph>Easy peasy.</paragraph>
|
|
||||||
|
|
||||||
<h2 class="text-2xl">Project Structure</h2>
|
|
||||||
<hr class="mb-6">
|
|
||||||
|
|
||||||
<paragraph>For any big C projects, a project structure is very important. It helps to organize and keep track of our
|
|
||||||
code. But for smaller projects, or just for testing purposes, a project structure could be too
|
|
||||||
redundant.
|
|
||||||
</paragraph>
|
|
||||||
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
project/
|
|
||||||
├── src/ # Source files (*.c, main.c)
|
|
||||||
│ └── main.c # Main program file
|
|
||||||
├── include/ # Header files (*.h)
|
|
||||||
├── lib/ # Library object files and archives
|
|
||||||
├── bin/ # Executable binaries
|
|
||||||
├── build/ # Temporary files (*.o)
|
|
||||||
├── tests/ # Test files
|
|
||||||
└── Makefile # Build script
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2 class="text-2xl">Compiling</h2>
|
|
||||||
<hr class="mb-6">
|
|
||||||
|
|
||||||
<paragraph>
|
|
||||||
Makefiles are very useful, and becomes increasingly useful, the bigger the project gets. A makefile simplifies the
|
|
||||||
compilation process, as all of the compile flags can be gathered inside a single file. It makes it possible to
|
|
||||||
dynamically change the compilation depending on the system architecture or config. It also removes the need to
|
|
||||||
manually compile and link your objects together, every time you make a change.<br><br>
|
|
||||||
|
|
||||||
And with a bigger project, comes a big count of source files. That's where a makefile helps a lot, as it handles
|
|
||||||
and tracks all changes to each file, ensuring that it's only the changed files that gets re-compiled.<br><br>
|
|
||||||
|
|
||||||
So let's see a makefile in action. Below code is a simple Hello World application, that we will use a makefile to
|
|
||||||
compile. Although it's worth noting, that a program this small, a makefile is wildly redundant. But it does show
|
|
||||||
how it's set up in a simple environment.<br><br>
|
|
||||||
|
|
||||||
With this little example, we're doing a Hello World program, but fret not, we'll go into details in a later guide.
|
|
||||||
</paragraph>
|
|
||||||
|
|
||||||
<code-tag>hello.c</code-tag>
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
int main(){
|
|
||||||
printf("Hello, World!");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<code-tag>Makefile</code-tag>
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
# Makefile for hello.c
|
|
||||||
|
|
||||||
CC = gcc # C compiler
|
|
||||||
CFLAGS = -O2 # Compiler flags (optimization level)
|
|
||||||
|
|
||||||
hello: hello.o
|
|
||||||
$(CC) $(CFLAGS) -o $@ $^
|
|
||||||
|
|
||||||
hello.o: hello.c
|
|
||||||
$(CC) $(CFLAGS) -c $<
|
|
||||||
|
|
||||||
run:
|
|
||||||
./hello
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f *.o hello
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<paragraph>
|
|
||||||
For anyone not programming in a language that uses the <code-tag>make</code-tag> makefile, this might look rather off-putting.
|
|
||||||
But worry not, because at the end of the day, it's simply just some rules, that the compiler follows to compile your program.
|
|
||||||
</paragraph>
|
|
||||||
|
|
||||||
<ul class="mb-6">
|
|
||||||
<li>> <code-tag>hello: hello.o</code-tag></li>
|
|
||||||
<li class="pb-2">> > Here, the program "hello" depends on the object file "hello.o".</li>
|
|
||||||
|
|
||||||
<li>> <code-tag>$(CC) $(CFLAGS) -o $@ $^</code-tag></li>
|
|
||||||
<li class="pb-2">> > This one compiles the object files into the program.</li>
|
|
||||||
|
|
||||||
<li>> <code-tag>hello.o: hello.c</code-tag></li>
|
|
||||||
<li class="pb-2">> > Here, the object file "hello.o" depends on the source file "hello.c".</li>
|
|
||||||
|
|
||||||
<li>> <code-tag>$(CC) $(CFLAGS) -c $<</code-tag></li>
|
|
||||||
<li class="pb-2">> > This one compiles the source files into the object files.</li>
|
|
||||||
|
|
||||||
<li>> <code-tag>run: ./hello</code-tag></li>
|
|
||||||
<li class="pb-2">> > This runs the program if you execute <code-tag>make run</code-tag></li>
|
|
||||||
|
|
||||||
<li>> <code-tag>clean: rm -f *.o hello</code-tag></li>
|
|
||||||
<li class="pb-2">> > Here, the object files gets removed when running <code-tag>make clean</code-tag></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<paragraph>
|
|
||||||
A quick note. It's very important that whenever something is indented in a makefile, that it's indented with a tab,
|
|
||||||
and not 4 spaces. It needs to be a tab character.<br><br>
|
|
||||||
|
|
||||||
Now simply run the makefile with the following command.
|
|
||||||
</paragraph>
|
|
||||||
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
$ make
|
|
||||||
gcc -O2 -c hello.c
|
|
||||||
gcc -O2 -o hello hello.o
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<paragraph>
|
|
||||||
We have now successfully compiled the program with the help of a makefile. Now simply run the program and we'll
|
|
||||||
see the output.
|
|
||||||
</paragraph>
|
|
||||||
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
$ ./hello
|
|
||||||
Hello, World!
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<paragraph>If we run <code-tag>make run</code-tag> command instead, the output should look pretty much the same.</paragraph>
|
|
||||||
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
$ make run
|
|
||||||
./hello
|
|
||||||
Hello, World!
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
@ -1,169 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import PageStart from "../tags/PageStart.vue";
|
|
||||||
import Paragraph from "../tags/Paragraph.vue";
|
|
||||||
import CodeTag from "../tags/CodeTag.vue";
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
|
|
||||||
<page-start>Calls, Methods, Functions and Subroutines</page-start>
|
|
||||||
|
|
||||||
<paragraph>In Fortran, there is no such thing as methods, but functions and subroutines instead. Fortran, compared to
|
|
||||||
other C-like programming languages, executes functions and subroutines differently. And what even is a subroutine?
|
|
||||||
Well, fret not, for we will discuss that in this post.<br><br>
|
|
||||||
|
|
||||||
<code-tag>function</code-tag>s are pretty much the same as methods in newer programming languages. They take in an input, and return an
|
|
||||||
output. They can also just take an input, and save it to a file. Or they could also just return a constant value.
|
|
||||||
At the end of the day, it's just a piece of code that is usually reused between multiple parts of the program.<br><br>
|
|
||||||
|
|
||||||
<code-tag>subroutine</code-tag>s are almost the exact same as functions. One such difference is that subroutine doesn't return anything,
|
|
||||||
in the traditional sense. If functions return a modified version of the input, a subroutine modifies the input data
|
|
||||||
in place.<br><br>
|
|
||||||
|
|
||||||
A subroutines parameters are often annotated inside the code block, with an intent. Observe the code below:</paragraph>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
module PlusHelper
|
|
||||||
implicit none
|
|
||||||
|
|
||||||
public :: plus_two
|
|
||||||
contains
|
|
||||||
subroutine plus_two (number)
|
|
||||||
integer, intent (out) :: number
|
|
||||||
number = number + 2
|
|
||||||
end subroutine plus_two
|
|
||||||
|
|
||||||
end module PlusHelper
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<paragraph>It's fairly easy to understand, really. We tell the compiler that <code-tag>number</code-tag> is intended
|
|
||||||
to be used and modified. <code-tag>intent()</code-tag> is a keyword used to hint and guide the compiler in what to do
|
|
||||||
with the value, deep down when compiling to machine code.<br><br>
|
|
||||||
|
|
||||||
<code-tag>in</code-tag> tells the compiler that the value is only used, but not modified. <code-tag>out</code-tag>
|
|
||||||
tells the compiler that the value is returned to the caller. We'll show how it's returned later on. <code-tag>inout</code-tag>
|
|
||||||
tells the compiler that the value is used, modified and then returned.<br><br>
|
|
||||||
|
|
||||||
As we can see with the code, <code-tag>number</code-tag> is being added by 2, and then returned. We'll see how the
|
|
||||||
value is used in the caller later.<br><br>
|
|
||||||
|
|
||||||
Let's show another example, that showcases this functionality a little better:</paragraph>
|
|
||||||
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
module MultiplyHelper
|
|
||||||
implicit none
|
|
||||||
|
|
||||||
public :: multiply_by
|
|
||||||
contains
|
|
||||||
subroutine multiply (number, multiply)
|
|
||||||
integer, intent(out) :: number
|
|
||||||
integer, intent(in) :: multiply
|
|
||||||
|
|
||||||
number = number * multiply
|
|
||||||
end subroutine multiply
|
|
||||||
|
|
||||||
end module MultiplyHelper
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<paragraph>As we can see with the code, it just returns the <code-tag>number</code-tag> after it has been multiplied by
|
|
||||||
the <code-tag>multiply</code-tag> value. Now let's see how we call the subroutine:</paragraph>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
program hello
|
|
||||||
use PlusHelper, only: plus_two
|
|
||||||
use MultiplyHelper, only: multiply_by
|
|
||||||
implicit none
|
|
||||||
|
|
||||||
integer :: number = 5
|
|
||||||
print *, number
|
|
||||||
|
|
||||||
call plus_two(number)
|
|
||||||
print *, number
|
|
||||||
|
|
||||||
call multiply_by(number, 2)
|
|
||||||
print *, number
|
|
||||||
end program hello
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<paragraph>And the output looks like this:</paragraph>
|
|
||||||
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
$ ./main
|
|
||||||
5
|
|
||||||
7
|
|
||||||
14
|
|
||||||
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<paragraph>That was pretty simply. That's how subroutines works. Now let's go over functions. First we start by defining
|
|
||||||
out function.</paragraph>
|
|
||||||
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
function divide_by(number, divide) result(return)
|
|
||||||
integer, intent(in) :: number
|
|
||||||
integer, intent(in) :: divide
|
|
||||||
integer :: return
|
|
||||||
|
|
||||||
return = number / divide
|
|
||||||
end function divide_by
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<paragraph>As we can see, it's almost like we're defining a subroutine. Do notice that we're still using the
|
|
||||||
<code-tag>intent</code-tag> keyword. We define out return as an integer as well. Also note that we're dividing integers,
|
|
||||||
and not floats. So the numbers are prone to rounding.<br><br>
|
|
||||||
|
|
||||||
Let's take a look on how we call a function.</paragraph>
|
|
||||||
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
program hello
|
|
||||||
use PlusHelper, only: plus_two
|
|
||||||
use MultiplyHelper, only: multiply_by
|
|
||||||
implicit none
|
|
||||||
|
|
||||||
integer :: divide_by
|
|
||||||
integer :: number = 5
|
|
||||||
print *, number
|
|
||||||
|
|
||||||
call plus_two(number)
|
|
||||||
print *, number
|
|
||||||
|
|
||||||
call multiply_by(number, 2)
|
|
||||||
print *, number
|
|
||||||
print *, divide_by(number, 2)
|
|
||||||
end program hello
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<paragraph>We create an <code-tag>integer</code-tag> that serves as the return for out function <code-tag>divide_by(n, k)</code-tag>.
|
|
||||||
And we call it just by writing the function name with it's parameters.<br><br>
|
|
||||||
|
|
||||||
The output looks like this:
|
|
||||||
</paragraph>
|
|
||||||
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
$ ./main
|
|
||||||
5
|
|
||||||
7
|
|
||||||
14
|
|
||||||
7
|
|
||||||
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<paragraph class="font-bold">TLDR: Functions are assigned as variables, and subroutines are imported and called with the <code-tag>call</code-tag> keyword.</paragraph>
|
|
||||||
|
|
||||||
</template>
|
|
@ -1,419 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
|
|
||||||
import CodeTag from "../tags/CodeTag.vue";
|
|
||||||
import Paragraph from "../tags/Paragraph.vue";
|
|
||||||
import PageStart from "../tags/PageStart.vue";
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<page-start>Data Types</page-start>
|
|
||||||
|
|
||||||
<paragraph>Just like any other programming language that has datatypes, Fortran has datatypes as well. The big difference, from
|
|
||||||
other languages, of cause, is how they're created and assigned. If you're a developer of, for example, C#, Java or
|
|
||||||
even Python, you will feel the difference pretty fast.<br><br>
|
|
||||||
|
|
||||||
Let's look at a small list of some common types.</paragraph>
|
|
||||||
|
|
||||||
<ul class="mb-6">
|
|
||||||
<li>> <CodeTag>integer</CodeTag></li>
|
|
||||||
<li>> <code-tag>real</code-tag></li>
|
|
||||||
<li>> <code-tag>double precision</code-tag></li>
|
|
||||||
<li>> <code-tag>logical</code-tag></li>
|
|
||||||
<li>> <code-tag>character</code-tag></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<paragraph><code-tag>integer</code-tag> is, if you hadn't guessed, a whole number. Like most languages,
|
|
||||||
<code-tag>int</code-tag>. The <code-tag>real</code-tag> type is like a
|
|
||||||
<code-tag>float</code-tag>. But the difference with Fortran types, in general, is that you have "less" types,
|
|
||||||
but you have more control over those types, making it essentially the same as if you had more types. More on that later.<br><br>
|
|
||||||
|
|
||||||
The <code-tag>double precision</code-tag> is a double, obviously. And as you have probably guessed at
|
|
||||||
this point, <code-tag>logical</code-tag> is a boolean. <code-tag>character</code-tag>
|
|
||||||
however, is a little bit different. In "new" programming terms, it would be an array of characters that behaves
|
|
||||||
like a string. Or like in SQL: <code-tag>VARCHAR(256)</code-tag>.</paragraph>
|
|
||||||
|
|
||||||
<h2 class="text-2xl">integer</h2>
|
|
||||||
<hr class="mb-6">
|
|
||||||
|
|
||||||
<paragraph>In Fortran, you can specify the size of an integer at declaration. You do that with <code-tag>(kind = n)</code-tag>.
|
|
||||||
So if you want a 16 bit integer, you do <code-tag>integer(kind = 16)</code-tag>. Observe the following code example.
|
|
||||||
As an exercise for the reader, try to imagine what would be printed to the terminal.<br><br>
|
|
||||||
|
|
||||||
*Do note that we're using Fortran 90, and not the newer versions that supports unsigned integers.<a href="#footnote-1">[1]</a>
|
|
||||||
</paragraph>
|
|
||||||
|
|
||||||
<code-tag>main.f90</code-tag>
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
program hello
|
|
||||||
implicit none
|
|
||||||
|
|
||||||
integer :: int1;
|
|
||||||
integer(kind = 2) :: int2;
|
|
||||||
integer(kind = 4) :: int4;
|
|
||||||
integer(kind = 8) :: int8;
|
|
||||||
integer(kind = 16) :: int16;
|
|
||||||
|
|
||||||
print *, 'int'
|
|
||||||
print *, huge(int1)
|
|
||||||
print *
|
|
||||||
print *, 'kind = 2'
|
|
||||||
print *, huge(int2)
|
|
||||||
print *
|
|
||||||
print *, 'kind = 4'
|
|
||||||
print *, huge(int4)
|
|
||||||
print *
|
|
||||||
print *, 'kind = 8'
|
|
||||||
print *, huge(int8)
|
|
||||||
print *
|
|
||||||
print *, 'kind = 16'
|
|
||||||
print *, huge(int16)
|
|
||||||
|
|
||||||
end program hello
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<paragraph>Now, as the astute reader might have already figured, the output would look like this:</paragraph>
|
|
||||||
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
> gfortran main.f90
|
|
||||||
> ./a.out
|
|
||||||
int
|
|
||||||
2147483647
|
|
||||||
|
|
||||||
kind = 2
|
|
||||||
32767
|
|
||||||
|
|
||||||
kind = 4
|
|
||||||
2147483647
|
|
||||||
|
|
||||||
kind = 8
|
|
||||||
9223372036854775807
|
|
||||||
|
|
||||||
kind = 16
|
|
||||||
170141183460469231731687303715884105727
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<paragraph>The <code-tag>huge(n)</code-tag> function simply assigns the highest largest number of any integer,
|
|
||||||
real or array type of any kind.<br><br>
|
|
||||||
|
|
||||||
Any integer without a kind, is automatically a 4 byte integer. Integers with kind 2, is 2 bytes big. Integers with
|
|
||||||
kind 4 is 4 bytes big. And so on and so forth.<br><br>
|
|
||||||
|
|
||||||
Usually, unless your working with huge datasets, <code-tag>integer</code-tag> or if you want to be more semantic,
|
|
||||||
<code-tag>integer(kind = 4)</code-tag> would be more than sufficient to work with.</paragraph>
|
|
||||||
|
|
||||||
<h2 class="text-2xl">real</h2>
|
|
||||||
<hr class="mb-6">
|
|
||||||
|
|
||||||
<paragraph>The <code-tag>real</code-tag> type is, in most other languages, a <code-tag>float</code-tag>. And with
|
|
||||||
integers, real can also be specified with a <code-tag>kind(n)</code-tag> modifier. Observe this example:</paragraph>
|
|
||||||
|
|
||||||
<code-tag>main.f90</code-tag>
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
program hello
|
|
||||||
implicit none
|
|
||||||
|
|
||||||
real :: real1;
|
|
||||||
real(kind = 4) real4;
|
|
||||||
real(kind = 8) real8;
|
|
||||||
real(kind = 16) real16;
|
|
||||||
|
|
||||||
print *, 'real'
|
|
||||||
print *, huge(real1)
|
|
||||||
print *, tiny(real1)
|
|
||||||
print *
|
|
||||||
print *, 'kind = 4'
|
|
||||||
print *, huge(real4)
|
|
||||||
print *, tiny(real4)
|
|
||||||
print *
|
|
||||||
print *, 'kind = 8'
|
|
||||||
print *, huge(real8)
|
|
||||||
print *, tiny(real8)
|
|
||||||
print *
|
|
||||||
print *, 'kind = 16'
|
|
||||||
print *, huge(real16)
|
|
||||||
print *, tiny(real16)
|
|
||||||
|
|
||||||
end program hello
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<paragraph>The output:</paragraph>
|
|
||||||
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
> gfortran main.f90
|
|
||||||
> ./a.out
|
|
||||||
real
|
|
||||||
3.40282347E+38
|
|
||||||
1.17549435E-38
|
|
||||||
|
|
||||||
real(kind = 4)
|
|
||||||
3.40282347E+38
|
|
||||||
1.17549435E-38
|
|
||||||
|
|
||||||
real(kind = 8)
|
|
||||||
1.7976931348623157E+308
|
|
||||||
2.2250738585072014E-308
|
|
||||||
|
|
||||||
real(kind = 16)
|
|
||||||
1.18973149535723176508575932662800702E+4932
|
|
||||||
3.36210314311209350626267781732175260E-4932
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<paragraph>As you can see here, we have included a new print statement. <code-tag>tiny(n)</code-tag> returns
|
|
||||||
the smallest positive number of a real kind. That function is not available for integers.</paragraph>
|
|
||||||
|
|
||||||
<h2 class="text-2xl">double precision</h2>
|
|
||||||
<hr class="mb-6">
|
|
||||||
|
|
||||||
<paragraph><code-tag>double precision</code-tag> is pretty much just a bigger version of real. All of the same rules apply
|
|
||||||
to double precision as the real type.</paragraph>
|
|
||||||
|
|
||||||
<code-tag>main.f90</code-tag>
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
program hello
|
|
||||||
implicit none
|
|
||||||
|
|
||||||
double precision :: double;
|
|
||||||
|
|
||||||
print *, 'real'
|
|
||||||
print *, huge(double)
|
|
||||||
print *, tiny(double)
|
|
||||||
|
|
||||||
end program hello
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<paragraph>And the output looks like this:</paragraph>
|
|
||||||
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
> gfortran main.f90
|
|
||||||
> ./a.out
|
|
||||||
real
|
|
||||||
1.7976931348623157E+308
|
|
||||||
2.2250738585072014E-308
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<paragraph><code-tag>double precision</code-tag> does not support the kind modifier. A double precision number is
|
|
||||||
also the same as an 8 byte real.</paragraph>
|
|
||||||
|
|
||||||
<h2 class="text-2xl">logical</h2>
|
|
||||||
<hr class="mb-6">
|
|
||||||
|
|
||||||
<paragraph><code-tag>logical</code-tag> is a boolean. It's either true or false. But a funny thing with the logical type in
|
|
||||||
Fortran, compared to other languages, is that you can define the size of it. The logical type supports the
|
|
||||||
<code-tag>kind(n)</code-tag> modifier.<br><br>
|
|
||||||
|
|
||||||
A good reason for the different sized logical, is optimization. Some systems handles larger object better than smaller,
|
|
||||||
or some systems handles smaller objects better. It all depends on the architecture.</paragraph>
|
|
||||||
|
|
||||||
<code-tag>main.f90</code-tag>
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
program hello
|
|
||||||
implicit none
|
|
||||||
|
|
||||||
logical :: bool;
|
|
||||||
logical(kind = 1) :: bool1;
|
|
||||||
logical(kind = 2) :: bool2;
|
|
||||||
logical(kind = 4) :: bool4;
|
|
||||||
logical(kind = 8) :: bool8;
|
|
||||||
logical(kind = 16) :: bool16;
|
|
||||||
|
|
||||||
print *, 'logical'
|
|
||||||
print *, 'value: ', bool
|
|
||||||
print *, 'size: ', sizeof(bool)
|
|
||||||
print *
|
|
||||||
print *, 'value: ', bool1
|
|
||||||
print *, 'size: ', sizeof(bool1)
|
|
||||||
print *
|
|
||||||
print *, 'value: ', bool2
|
|
||||||
print *, 'size: ', sizeof(bool2)
|
|
||||||
print *
|
|
||||||
print *, 'value: ', bool4
|
|
||||||
print *, 'size: ', sizeof(bool4)
|
|
||||||
print *
|
|
||||||
print *, 'value: ', bool8
|
|
||||||
print *, 'size: ', sizeof(bool8)
|
|
||||||
print *
|
|
||||||
print *, 'value: ', bool16
|
|
||||||
print *, 'size: ', sizeof(bool16)
|
|
||||||
|
|
||||||
end program hello
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<paragraph>Now I have a small exercise for the reader again. Let's assume that we are using <code-tag>gfortran</code-tag>
|
|
||||||
without specifying an optimization level. What do you think the output would look like?</paragraph>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
> gfortran main.f90
|
|
||||||
> ./a.out
|
|
||||||
logical
|
|
||||||
value: T
|
|
||||||
size: 4
|
|
||||||
|
|
||||||
value: T
|
|
||||||
size: 1
|
|
||||||
|
|
||||||
value: T
|
|
||||||
size: 2
|
|
||||||
|
|
||||||
value: T
|
|
||||||
size: 4
|
|
||||||
|
|
||||||
value: F
|
|
||||||
size: 8
|
|
||||||
|
|
||||||
value: T
|
|
||||||
size: 16
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<paragraph>Huh, that was weird. The 8 bit logical is false, while the others are true. The reason for this behavior
|
|
||||||
could be a multitude of things. One could be optimization, as the compiler tries to make the program faster. And
|
|
||||||
by setting the 8 bit logical to false. It could also be how an unassigned logical is represented. For more information,
|
|
||||||
check the footnote number 2. <a href="#footnote-1">[2]</a><br><br>
|
|
||||||
|
|
||||||
A good programming practise is to always assign your logical when creating them.</paragraph>
|
|
||||||
|
|
||||||
<code-tag>main.f90</code-tag>
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
logical :: bool = .true.;
|
|
||||||
logical(kind = 1) :: bool1 = .true.;
|
|
||||||
logical(kind = 2) :: bool2 = .true.;
|
|
||||||
logical(kind = 4) :: bool4 = .true.;
|
|
||||||
logical(kind = 8) :: bool8 = .true.;
|
|
||||||
logical(kind = 16) :: bool16 = .true.;
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<paragraph>Now, the output looks as expected.</paragraph>
|
|
||||||
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
> gfortran main.f90
|
|
||||||
> ./a.out
|
|
||||||
logical
|
|
||||||
value: T
|
|
||||||
size: 4
|
|
||||||
|
|
||||||
value: T
|
|
||||||
size: 1
|
|
||||||
|
|
||||||
value: T
|
|
||||||
size: 2
|
|
||||||
|
|
||||||
value: T
|
|
||||||
size: 4
|
|
||||||
|
|
||||||
value: T
|
|
||||||
size: 8
|
|
||||||
|
|
||||||
value: T
|
|
||||||
size: 16
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2 class="text-2xl">character</h2>
|
|
||||||
<hr class="mb-6">
|
|
||||||
|
|
||||||
<paragraph><code-tag>character</code-tag> in fortran can be seen as either a <code-tag>char</code-tag> or
|
|
||||||
a <code-tag>string</code-tag> in other languages, depending on the length you give it.<br><br>
|
|
||||||
|
|
||||||
Observe the example below.</paragraph>
|
|
||||||
|
|
||||||
<code-tag>main.f90</code-tag>
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
program hello
|
|
||||||
implicit none
|
|
||||||
|
|
||||||
character :: char;
|
|
||||||
character(len = 10) :: char2 = 'a';
|
|
||||||
|
|
||||||
print *, 'character';
|
|
||||||
print *, 'value: ', char;
|
|
||||||
print *, 'size: ', sizeof(char);
|
|
||||||
print *
|
|
||||||
print *, 'value: ', char2;
|
|
||||||
print *, 'size: ', sizeof(char2);
|
|
||||||
print *
|
|
||||||
print *, 'value: ', char2//'lol';
|
|
||||||
print *, 'size: ', sizeof(char2);
|
|
||||||
|
|
||||||
end program hello
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<paragraph>Output looks like this:</paragraph>
|
|
||||||
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
> gfortran main.f90
|
|
||||||
> ./a.out
|
|
||||||
character
|
|
||||||
value: 4
|
|
||||||
size: 1
|
|
||||||
|
|
||||||
value: a
|
|
||||||
size: 10
|
|
||||||
|
|
||||||
value: a lol
|
|
||||||
size: 10
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<paragraph>lol. With Fortran, if you create a character, with a certain size, but only assign it a smaller vallue,
|
|
||||||
the trailing indexes in the character will be filled with whitespace.<br><br>
|
|
||||||
|
|
||||||
To mitigate this, we could either set the correct length when creating the character, or we could use the <code-tag>trim(value)</code-tag>
|
|
||||||
function. It removes trailing whitespaces from strings.</paragraph>
|
|
||||||
|
|
||||||
<code-tag>main.f90</code-tag>
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
trim(char2)//'lol';
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<paragraph>Now, the output should be fixed:</paragraph>
|
|
||||||
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
> gfortran main.f90
|
|
||||||
> ./a.out
|
|
||||||
character
|
|
||||||
value:
|
|
||||||
size: 1
|
|
||||||
|
|
||||||
value: a
|
|
||||||
size: 10
|
|
||||||
|
|
||||||
value: a lol
|
|
||||||
size: 10
|
|
||||||
|
|
||||||
with trim
|
|
||||||
value: alol
|
|
||||||
size: 10
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>Footnotes:</p>
|
|
||||||
<ul>
|
|
||||||
<li id="footnote-1">[1] <a href="https://gcc.gnu.org/onlinedocs/gfortran/Unsigned-integers.html" class="underline">unsigned integers with gfortran</a></li>
|
|
||||||
<li id="footnote-2">[2] <a href="https://stackoverflow.com/a/71190625" class="underline">Why would using uninitialized variables in Fortran ever work? [duplicate]</a></li>
|
|
||||||
</ul>
|
|
||||||
</template>
|
|
@ -1,18 +1,14 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|
||||||
import Paragraph from "../tags/Paragraph.vue";
|
|
||||||
import CodeTag from "../tags/CodeTag.vue";
|
|
||||||
import PageStart from "../tags/PageStart.vue";
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<page-start>Hello World In Fortran 90</page-start>
|
<div>
|
||||||
|
<h1 class="text-3xl">Hello World In Fortran 90</h1>
|
||||||
|
<hr>
|
||||||
|
<p></p>
|
||||||
|
|
||||||
<paragraph>A Hello World program is always a great step into a new programming language. It gives a simple oversight into
|
<div class="font-mono">
|
||||||
the build process of said language. And with a simple project come a simple intro (mostly). But fret not, Fortran
|
|
||||||
can be simple or complex, depending on the size of the project.</paragraph>
|
|
||||||
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
<pre><code class="text-sm">
|
||||||
program hello
|
program hello
|
||||||
implicit none
|
implicit none
|
||||||
@ -21,16 +17,16 @@ end program hello
|
|||||||
</code></pre>
|
</code></pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<paragraph>In the good ol' days (before FORTRAN 77), when printing to console, you would write <code-tag>write(*,*)</code-tag>,
|
<p>In the good ol' days (before FORTRAN 77), when printing to console, you would write <span><code>write(*,*)</code></span>,
|
||||||
but with the release of FORTRAN 77, that became redundant, as you could use the newest keyword: <code-tag>print</code-tag>. <br><br>
|
but with the release of FORTRAN 77, that became redundant, as you could use the newest keyword: <span><code>print</code></span>.</p>
|
||||||
|
<br>
|
||||||
|
|
||||||
With modern compilers, running the newest Fortran standards, <code-tag>write(*,*) 'Hello world!'</code-tag>
|
<p>With modern compilers, running the newest Fortran standards, <span><code>write(*,*) 'Hello world!'</code> and <code>print *, 'Hello world!'</code></span>
|
||||||
and <code-tag>print *, 'Hello world!'</code-tag>
|
will compile to the exact same assembly. So if you only need to print something to stdout, just use <span><code>print *</code></span>
|
||||||
will compile to the exact same assembly. So if you only need to print something to stdout, just use <code-tag>print *</code-tag>
|
as it conveys the meaning of the code better. Plus we don't need the full functionality of <span><code>write(*,*)</code></span>
|
||||||
as it conveys the meaning of the code better. Plus we don't need the full functionality of <code-tag>write(*,*)</code-tag>
|
in this example.</p>
|
||||||
in this example.</paragraph>
|
|
||||||
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
<div class="font-mono">
|
||||||
<pre><code class="text-sm">
|
<pre><code class="text-sm">
|
||||||
$ gfortran -o hello main.f90
|
$ gfortran -o hello main.f90
|
||||||
$ ./hello
|
$ ./hello
|
||||||
@ -38,11 +34,11 @@ $ ./hello
|
|||||||
</code></pre>
|
</code></pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<paragraph>Now, hear me out, why not spice up the program a little bit more? What if we want to read user input? Well, fret
|
<p>Now, hear me out, why not spice up the program a little bit more? What if we want to read user input? Well, fret
|
||||||
not my friend, because I have just the solution for you then. All we gotta do is to read from the terminal, and
|
not my friend, because I have just the solution for you then. All we gotta do is to read from the terminal, and
|
||||||
then print out the value.</paragraph>
|
then print out the value.</p>
|
||||||
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
<div class="font-mono">
|
||||||
<pre><code class="text-sm">
|
<pre><code class="text-sm">
|
||||||
program hello
|
program hello
|
||||||
implicit none
|
implicit none
|
||||||
@ -61,28 +57,31 @@ end program hello
|
|||||||
</code></pre>
|
</code></pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<paragraph>So what we're seeing here, is that we have created two variables: <code-tag>usertxt</code-tag>
|
<p>So what we're seeing here, is that we have created two variables: <span><code>usertxt</code> and <code>ios</code></span>.
|
||||||
and <code-tag>ios</code-tag>.<code-tag>usertxt</code-tag> is the input we're reading from the terminal. Although since Fortran 90 doesn't
|
<span><code>usertxt</code></span> is the input we're reading from the terminal. Although since Fortran 90 doesn't
|
||||||
have an explicit string type, doesn't mean we can't read or write text, as the <code-tag>character</code-tag>
|
have an explicit string type, doesn't mean we can't read or write text, as the <span><code>character</code></span>
|
||||||
type is just an array of 1000 characters long. It doesn't have to be 1000 characters, but it's what I chose on a
|
type is just an array of 1000 characters long. It doesn't have to be 1000 characters, but it's what I chose on a
|
||||||
whim.<br><br>
|
whim.</p>
|
||||||
|
<br>
|
||||||
|
|
||||||
The other variable, <code-tag>ios</code-tag>, I probably don't need to introduce, as it's just an integer.
|
<p>The other variable, <span><code>ios</code></span>, I probably don't need to introduce, as it's just an integer.
|
||||||
But what control-flow this value holds, I feel is quite important, as a lot of file-based business logic makes
|
But what control-flow this value holds, I feel is quite important, as a lot of file-based business logic makes
|
||||||
use of it.<br><br>
|
use of it.</p>
|
||||||
|
<br>
|
||||||
|
|
||||||
Introducing, <code-tag>iostat</code-tag>. AKA, Input/Output Status Specifier. It indicates the status of the
|
<p>Introducing, <span><code>iostat</code></span>. AKA, Input/Output Status Specifier. It indicates the status of the
|
||||||
I/O operation. If the integer is positive, it indicates an error code. If it's negative, it indicates an end of file
|
I/O operation. If the integer is positive, it indicates an error code. If it's negative, it indicates an end of file
|
||||||
condition. If it's zero, then it does not indicate anything yet. No error, no End Of File, no particular condition
|
condition. If it's zero, then it does not indicate anything yet. No error, no End Of File, no particular condition
|
||||||
has triggered yet.<br><br>
|
has triggered yet.</p>
|
||||||
|
<br>
|
||||||
|
|
||||||
So in this case, where we check if <code-tag>ios</code-tag> is End Of File, then that means if we input an
|
<p>So in this case, where we check if <span><code>ios</code></span> is End Of File, then that means if we input an
|
||||||
End Of File key combination (Ctrl+D on Unix/Linux, and Ctrl+Z on Windows), then the program would stop immediately.
|
End Of File key combination (Ctrl+D on Unix/Linux, and Ctrl+Z on Windows), then the program would stop immediately.
|
||||||
We use the <code-tag>trim()</code-tag> function to remove any trailing whitespaces. That's because, if you
|
We use the <span><code>trim()</code></span> function to remove any trailing whitespaces. That's because, if you
|
||||||
make a character array longer than the actual text, it will be filled with whitespace after the text. So now the output
|
make a character array longer than the actual text, it will be filled with whitespace after the text. So now the output
|
||||||
looks like this:</paragraph>
|
looks like this:</p>
|
||||||
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
<div class="font-mono">
|
||||||
<pre><code class="text-sm">
|
<pre><code class="text-sm">
|
||||||
$ gfortran -o hello main.f90
|
$ gfortran -o hello main.f90
|
||||||
$ ./hello
|
$ ./hello
|
||||||
@ -91,4 +90,5 @@ Hello world :D
|
|||||||
Hello world :D
|
Hello world :D
|
||||||
</code></pre>
|
</code></pre>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
@ -1,28 +1,29 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|
||||||
import PageStart from "../tags/PageStart.vue";
|
|
||||||
import Paragraph from "../tags/Paragraph.vue";
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<page-start>Fortran</page-start>
|
<div>
|
||||||
|
<h1 class="text-3xl">Fortran</h1>
|
||||||
<paragraph>Fortran (Formula Translation), is one of the ancient languages somehow still in use as of today. First introduced
|
<hr>
|
||||||
|
<p>Fortran (Formula Translation), is one of the ancient languages somehow still in use as of today. First introduced
|
||||||
in the 1950s by a team at IBM, Fortran was designed specifically for scientific and engineering applications,
|
in the 1950s by a team at IBM, Fortran was designed specifically for scientific and engineering applications,
|
||||||
where its ability to efficiently handle complex mathematical operations far outperformed rivaling languages at the
|
where its ability to efficiently handle complex mathematical operations far outperformed rivaling languages at the
|
||||||
time.<br><br>
|
time.</p>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<p>
|
||||||
Over the years, Fortran has undergone numerous updates and revisions, with the most recent standard being Fortran
|
Over the years, Fortran has undergone numerous updates and revisions, with the most recent standard being Fortran
|
||||||
2023. Even with the popularity of newer languages, such as C++, Java, and Python, Fortran remains a popular choice
|
2023. Even with the popularity of newer languages, such as C++, Java, and Python, Fortran remains a popular choice
|
||||||
in many fields, including physics, chemistry, meteorology, and engineering, due to its performance. Even Nvidia
|
in many fields, including physics, chemistry, meteorology, and engineering, due to its performance. Even Nvidia
|
||||||
and Intel are still developing their compilers, as well as FOSS compilers such as gfortran and lfortran.</paragraph>
|
and Intel are still developing their compilers, as well as FOSS compilers such as gfortran and lfortran.</p>
|
||||||
|
<br>
|
||||||
|
|
||||||
<p>Table of contents:</p>
|
<p>Table of contents:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><RouterLink to="/Fortran/SetUp">> Set Up</RouterLink></li>
|
<li><RouterLink to="/Fortran/SetUp">> Set Up</RouterLink></li>
|
||||||
<li><RouterLink to="/Fortran/HelloWorld">> Hello World</RouterLink></li>
|
<li><RouterLink to="/Fortran/HelloWorld">> Hello World</RouterLink></li>
|
||||||
<li><RouterLink to="/Fortran/DataTypes">> Data Types</RouterLink></li>
|
|
||||||
<li><RouterLink to="/Fortran/Methods">> Method, Functions, Sub Routines and Calls</RouterLink></li>
|
|
||||||
<li><RouterLink to="/Fortran/ReadingAFile">> Reading A File</RouterLink></li>
|
<li><RouterLink to="/Fortran/ReadingAFile">> Reading A File</RouterLink></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
@ -1,20 +1,15 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|
||||||
import PageStart from "../tags/PageStart.vue";
|
|
||||||
import CodeTag from "../tags/CodeTag.vue";
|
|
||||||
import Paragraph from "../tags/Paragraph.vue";
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<page-start>Reading A File In Fortran 90</page-start>
|
<div>
|
||||||
|
<h1 class="text-3xl">Reading A File In Fortran 90</h1>
|
||||||
|
<hr>
|
||||||
|
<p></p>
|
||||||
|
|
||||||
<paragraph>Reading files in high level programming languages is rather easy. In C#, you would just create a
|
<code class="">
|
||||||
<code-tag>StreamReader</code-tag> object, and execute: <code-tag>streamReader.ReadLine()</code-tag> and bam,
|
|
||||||
you've read the first line of the file. Now just check if the string returned is null, in a while loop, and you've
|
|
||||||
read the whole file. Easy peasy.<br><br>
|
|
||||||
|
|
||||||
In Fortran 90, however, there is a little more than that. Not a lot more, to be honest, but there is a little more.
|
</code>
|
||||||
Especially if you're using Fortran 90, compared to newer versions. In Fortran 90, you have to read the file, line
|
</div>
|
||||||
by line.</paragraph>
|
|
||||||
</template>
|
</template>
|
@ -1,187 +1,93 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|
||||||
import CodeTag from "../tags/CodeTag.vue";
|
|
||||||
import PageStart from "../tags/PageStart.vue";
|
|
||||||
import Paragraph from "../tags/Paragraph.vue";
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<page-start>Setting Up The Environment</page-start>
|
<div>
|
||||||
|
<h1 class="text-3xl">Setting Up The Environment</h1>
|
||||||
|
<hr>
|
||||||
|
|
||||||
<paragraph>If you're familiar with C, then you would feel right at home with Fortran's build environment. There isn't really
|
<p>If you're familiar with C, then you would feel right at home with Fortran's build environment. There isn't really
|
||||||
an "official" compiler for the language, only a standard, that has to be implemented by the compilers. But there
|
an "official" compiler for the language, only a standard, that has to be implemented by the compilers. But there
|
||||||
are a lot of great compilers, that might as well be "official."<br><br>
|
are a lot of great compilers, that might as well be "official."</p>
|
||||||
|
<br>
|
||||||
|
|
||||||
The top listed compiler on Fortran's website, is the GNU Fortran compiler (gfortran). It's the one I will be using
|
<p>The top listed compiler on Fortran's website, is the GNU Fortran compiler (gfortran). It's the one I will be using
|
||||||
throughout the examples on the site. Unless stated otherwise. There are also some other notable compilers, that
|
throughout the examples on the site. Unless stated otherwise. There are also some other notable compilers, that
|
||||||
has some rather interesting qualities to them.
|
has some rather interesting qualities to them.</p>
|
||||||
</paragraph>
|
<br>
|
||||||
|
|
||||||
<p>Compilers:</p>
|
<p>Compilers:</p>
|
||||||
<ul class="mb-6">
|
<ul>
|
||||||
<li>> <a class="underline" href="https://lfortran.org/">lfortran</a> (This one can be used as an interactive
|
<li>> <a class="underline" href="https://lfortran.org/">lfortran</a> (This one can be used as an interactive
|
||||||
compiler, supports parsing all of the 2018 standard syntax and also compile Fortran to WebAssemply).</li>
|
compiler, supports parsing all of the 2018 standard syntax and also compile Fortran to WebAssemply).</li>
|
||||||
<li>> <a class="underline" href="https://developer.nvidia.com/hpc-sdk">NVIDIA HPC SDK</a> (This one comes with a whole lot of GPU
|
<li>> <a class="underline" href="https://developer.nvidia.com/hpc-sdk">NVIDIA HPC SDK</a> (This one comes with a whole lot of GPU
|
||||||
accelerated libraries).</li>
|
accelerated libraries).</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<br>
|
||||||
|
|
||||||
<paragraph>But we will be using gfortran. Through the examples on this site, I will mainly be focusing on developing on Linux. <br>
|
<p>But we will be using gfortran. Through the examples on this site, I will mainly be focusing on developing on Linux.</p>
|
||||||
First, we install the compiler.
|
<br>
|
||||||
</paragraph>
|
|
||||||
|
|
||||||
<p>For Fedora:</p>
|
<p>First, we install the compiler.</p>
|
||||||
<code-tag>$ sudo dnf install gcc-gfortran</code-tag>
|
<br>
|
||||||
|
|
||||||
<p>For ubuntu:</p>
|
<p>For Fedora.</p>
|
||||||
<code-tag>$ sudo apt install gfortran</code-tag>
|
<code>$ sudo dnf install gcc-gfortran</code>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
|
||||||
<paragraph>And that's it. Pretty easy.</paragraph>
|
<p>For ubuntu.</p>
|
||||||
|
<code>$ sudo apt install gfortran</code>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
|
||||||
<h2 class="text-2xl">Project Structure</h2>
|
<p>And that's it. Pretty easy.</p>
|
||||||
<hr class="mb-6">
|
<br>
|
||||||
|
|
||||||
<paragraph>When creating a Fortran project, or any project in general, you want a structure. There is a lot of different
|
<h1 class="text-3xl">Project Structure</h1>
|
||||||
layouts for the structure, but equal amongst them, is the <code-tag>src</code-tag> folder. That's where we keep all of out
|
<hr>
|
||||||
source code. Like <code-tag>*.f90, *.f95</code-tag> files.<br><br>
|
|
||||||
|
|
||||||
But other than that, most projects include a <code-tag>Makefile</code-tag> file, a
|
<p>When creating a Fortran project, or any project in general, you want a structure. There is a lot of different
|
||||||
<code-tag>library</code-tag>, <code-tag>test</code-tag>
|
layouts for the structure, but equal amongst them, is the <code>src</code> folder. That's where we keep all of out
|
||||||
and <code-tag>bin</code-tag> folder. Your layout doesn't need to look like this specifically, nor does it have to contain
|
source code. Like <code>*.f90, *.f95</code> files.</p>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<p>But other than that, most projects include a <code>Makefile</code> file, a <code>library</code>, <code>test</code>
|
||||||
|
and <code>bin</code> folder. Your layout doesn't need to look like this specifically, nor does it have to contain
|
||||||
the same folders. Each project is different, and so are the requirements. But this layout is simple, and great
|
the same folders. Each project is different, and so are the requirements. But this layout is simple, and great
|
||||||
for medium to large projects.<br><br>
|
for medium to large projects.</p>
|
||||||
|
<br>
|
||||||
|
|
||||||
But if we're doing micro-projects, as in like, a hello world application, a test application, or a small tool,
|
<p>But if we're doing micro-projects, as in like, a hello world application, a test application, or a small tool,
|
||||||
this layout is rather redundant, and in the examples on this site, we will only use it on bigger projects,
|
this layout is rather redundant, and in the examples on this site, we will only use it on bigger projects,
|
||||||
and we will let you know, when or how we set up the project.
|
and we will let you know, when or how we set up the project.</p>
|
||||||
</paragraph>
|
<br>
|
||||||
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
<div class="font-mono">
|
||||||
<pre><code class="text-sm">
|
<pre><code class="text-sm">
|
||||||
project/
|
project/
|
||||||
├── src/ # Source files (.f90, .f95, etc.)
|
├── src/ # Source files (.f90, .f95, etc.)
|
||||||
│ ├── modules/ # Module definitions
|
│ ├── modules/ # Module definitions
|
||||||
│ └── main.f90 # Main program file
|
│ └── main.f90 # Main program file
|
||||||
├── include/ # Include files (interface definitions)
|
├── include/ # Include files (e.g., interface definitions)
|
||||||
├── lib/ # Library object files and archives
|
├── lib/ # Library object files and archives
|
||||||
├── bin/ # Executable binaries
|
├── bin/ # Executable binaries
|
||||||
├── tests/ # Test files
|
├── tests/ # Test cases
|
||||||
└── Makefile # Build script
|
└── Makefile # Build script
|
||||||
</code></pre>
|
</code></pre>
|
||||||
</div>
|
</div>
|
||||||
|
<br>
|
||||||
|
|
||||||
<p>Notes:</p>
|
<p>Notes:</p>
|
||||||
<ul class="mb-6">
|
<ul>
|
||||||
<li>> <code-tag>src</code-tag> (This is where we keep all of out source code).</li>
|
<li>> <code>src</code> (This is where we keep all of out source code).</li>
|
||||||
<li>> <code-tag>modules</code-tag> (This is where we keep our classes. Or in Fortran-speak, modules).</li>
|
<li>> <code>modules</code> (This is where we keep our classes. Or in Fortran-speak, modules).</li>
|
||||||
<li>> <code-tag>include</code-tag> (This is where we keep our interfaces, that out modules will inherit from, if we're using Fortran 90 or above).</li>
|
<li>> <code>include</code> (This is where we keep our interfaces, that out modules will inherit from, if we're using Fortran 90 or above).</li>
|
||||||
<li>> <code-tag>bin</code-tag> (This is where the compiled program should end up in).</li>
|
<li>> <code>bin</code> (This is where the compiled program should end up in).</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<br>
|
||||||
|
|
||||||
<h2 class="text-2xl">Compiling</h2>
|
<p>Makefiles are very useful, and becomes increasingly useful, the bigger the project gets.</p> <!-- TODO: Continue from here. Show example. -->
|
||||||
<hr class="mb-6">
|
|
||||||
|
|
||||||
<paragraph>Makefiles are very useful, and becomes increasingly useful, the bigger the project gets. A makefile simplifies the
|
|
||||||
compilation process, as all of the compile flags can be gathered inside a single file. It makes it possible to
|
|
||||||
dynamically change the compilation depending on the system architecture or config. It also removes the need to
|
|
||||||
manually compile and link your objects together, every time you make a change.<br><br>
|
|
||||||
|
|
||||||
And with a bigger project, comes a big count of source files. That's where a makefile helps a lot, as it handles
|
|
||||||
and tracks all changes to each file, ensuring that it's only the changed files that gets re-compiled.<br><br>
|
|
||||||
|
|
||||||
So let's see a makefile in action. Below code is a simple Hello World application, that we will use a makefile to
|
|
||||||
compile. Although it's worth noting, that a program this small, a makefile is wildly redundant. But it does show
|
|
||||||
how it's set up in a simple environment.
|
|
||||||
</paragraph>
|
|
||||||
|
|
||||||
<code-tag>hello.f90</code-tag>
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
program hello
|
|
||||||
implicit none
|
|
||||||
print *, 'Hello, World!'
|
|
||||||
end program hello
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<code-tag>Makefile</code-tag>
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
FC = gfortran # Fortran compiler
|
|
||||||
FFLAGS = -O2 # Compiler flags (optimization level)
|
|
||||||
|
|
||||||
hello: hello.o
|
|
||||||
$(FC) $(FFLAGS) -o $@ $^
|
|
||||||
|
|
||||||
hello.o: hello.f90
|
|
||||||
$(FC) $(FFLAGS) -c $<
|
|
||||||
|
|
||||||
run:
|
|
||||||
./hello
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f *.o hello
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<paragraph>
|
|
||||||
The makefile, in the eyes of a modern programmer (C#, Python, JS, Etc) might look rather repulsive. But be not
|
|
||||||
afraid, because at the end of the day, it's simply just some rules, that the compiler follows to compile your program.
|
|
||||||
</paragraph>
|
|
||||||
|
|
||||||
<ul class="mb-6">
|
|
||||||
<li>> <code-tag>hello: hello.o</code-tag></li>
|
|
||||||
<li class="pb-2">> > Here, the program "hello" depends on the object file "hello.o".</li>
|
|
||||||
|
|
||||||
<li>> <code-tag>$(FC) $(FFLAGS) -o $@ $^</code-tag></li>
|
|
||||||
<li class="pb-2">> > This one compiles the object files into the program.</li>
|
|
||||||
|
|
||||||
<li>> <code-tag>hello.o: hello.f90</code-tag></li>
|
|
||||||
<li class="pb-2">> > Here, the object file "hello.o" depends on the source file "hello.f90".</li>
|
|
||||||
|
|
||||||
<li>> <code-tag>$(FC) $(FFLAGS) -c $<</code-tag></li>
|
|
||||||
<li class="pb-2">> > This one compiles the source files into the object files.</li>
|
|
||||||
|
|
||||||
<li>> <code-tag>run: ./hello</code-tag></li>
|
|
||||||
<li class="pb-2">> > This runs the program if you execute <code-tag>make run</code-tag></li>
|
|
||||||
|
|
||||||
<li>> <code-tag>clean: rm -f *.o hello</code-tag></li>
|
|
||||||
<li class="pb-2">> > Here, the object files gets removed when running <code-tag>make clean</code-tag></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<paragraph>
|
|
||||||
A quick note. It's very important that whenever something is indented in a makefile, that it's indented with a tab,
|
|
||||||
and not 4 spaces. It needs to be a tab character.<br><br>
|
|
||||||
|
|
||||||
Now simply run the makefile with the following command.
|
|
||||||
</paragraph>
|
|
||||||
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
$ make
|
|
||||||
gfortran -O2 -c hello.f90
|
|
||||||
gfortran -O2 -o hello hello.o
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<paragraph>
|
|
||||||
We have now successfully compiled the program with the help of a makefile. Now simply run the program and we'll
|
|
||||||
see the output.
|
|
||||||
</paragraph>
|
|
||||||
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
$ ./hello
|
|
||||||
Hello, World!
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<paragraph>The exact same should happen, if we run the next command instead.</paragraph>
|
|
||||||
|
|
||||||
<div class="font-mono shadow-lg shadow-slate-500 p-2 mb-6">
|
|
||||||
<pre><code class="text-sm">
|
|
||||||
$ make run
|
|
||||||
./hello
|
|
||||||
Hello, World!
|
|
||||||
</code></pre>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
11
src/components/Lisp/Lisp_Index.vue
Normal file
11
src/components/Lisp/Lisp_Index.vue
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
11
src/components/Pascal/Pascal_Index.vue
Normal file
11
src/components/Pascal/Pascal_Index.vue
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -1,3 +0,0 @@
|
|||||||
<template>
|
|
||||||
<code class="text-red-500"><slot/></code>
|
|
||||||
</template>
|
|
@ -1,4 +0,0 @@
|
|||||||
<template>
|
|
||||||
<h1 class="text-3xl"><slot></slot></h1>
|
|
||||||
<hr class="mb-6">
|
|
||||||
</template>
|
|
@ -1,3 +0,0 @@
|
|||||||
<template>
|
|
||||||
<p class="mb-6"><slot></slot></p>
|
|
||||||
</template>
|
|
20
src/main.ts
20
src/main.ts
@ -6,13 +6,11 @@ import App from './App.vue'
|
|||||||
import Home from "./components/Home.vue";
|
import Home from "./components/Home.vue";
|
||||||
import About from "./components/About.vue";
|
import About from "./components/About.vue";
|
||||||
import FortranIndex from "./components/Fortran/Fortran_Index.vue";
|
import FortranIndex from "./components/Fortran/Fortran_Index.vue";
|
||||||
|
import PascalIndex from "./components/Pascal/Pascal_Index.vue";
|
||||||
|
import LispIndex from "./components/Lisp/Lisp_Index.vue";
|
||||||
import FortranReadingFiles from "./components/Fortran/Fortran_Reading_Files.vue";
|
import FortranReadingFiles from "./components/Fortran/Fortran_Reading_Files.vue";
|
||||||
import FortranHelloWorld from "./components/Fortran/Fortran_Hello_World.vue";
|
import FortranHelloWorld from "./components/Fortran/Fortran_Hello_World.vue";
|
||||||
import FortranSetUp from "./components/Fortran/Fortran_Set_Up.vue";
|
import FortranSetUp from "./components/Fortran/Fortran_Set_Up.vue";
|
||||||
import FortranDataTypes from "./components/Fortran/Fortran_Data_Types.vue";
|
|
||||||
import FortranCallsMethodsFunctionsSubroutines from "./components/Fortran/Fortran_Calls_Methods_Functions_Subroutines.vue";
|
|
||||||
import CIndex from "./components/C/C_Index.vue";
|
|
||||||
import CSetUp from "./components/C/C_Set_Up.vue";
|
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(),
|
history: createWebHistory(),
|
||||||
@ -21,14 +19,14 @@ const router = createRouter({
|
|||||||
{path: '/About', name: 'About', component: About},
|
{path: '/About', name: 'About', component: About},
|
||||||
|
|
||||||
{path: '/Fortran', name: 'Fortran', component: FortranIndex},
|
{path: '/Fortran', name: 'Fortran', component: FortranIndex},
|
||||||
{path: '/Fortran/SetUp', name: 'F_SetUp', component: FortranSetUp},
|
{path: '/Fortran/SetUp', name: 'SetUp', component: FortranSetUp},
|
||||||
{path: '/Fortran/HelloWorld', name: 'F_HelloWorld', component: FortranHelloWorld},
|
{path: '/Fortran/HelloWorld', name: 'HelloWorld', component: FortranHelloWorld},
|
||||||
{path: '/Fortran/DataTypes', name: 'F_DataTypes', component: FortranDataTypes},
|
{path: '/Fortran/ReadingAFile', name: 'ReadingAFile', component: FortranReadingFiles},
|
||||||
{path: '/Fortran/Methods', name: 'F_Methods', component: FortranCallsMethodsFunctionsSubroutines},
|
|
||||||
{path: '/Fortran/ReadingAFile', name: 'F_ReadingAFile', component: FortranReadingFiles},
|
|
||||||
|
|
||||||
{path: '/C', name: 'C', component: CIndex},
|
{path: '/Pascal', name: 'Pascal', component: PascalIndex},
|
||||||
{path: '/C/SetUp', name: 'C_SetUp', component: CSetUp},
|
|
||||||
|
|
||||||
|
{path: '/Lisp', name: 'Lisp', component: LispIndex}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
:root {
|
:root {
|
||||||
font-family: Inter, system-ui, Avenir, Helvetica, Arial;
|
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||||
|
line-height: 1.5;
|
||||||
|
font-weight: 400;
|
||||||
|
|
||||||
font-synthesis: none;
|
font-synthesis: none;
|
||||||
text-rendering: optimizeLegibility;
|
text-rendering: optimizeLegibility;
|
||||||
|
@ -1,11 +1,20 @@
|
|||||||
/** @type {import('tailwindcss').Config} */
|
/** @type {import('tailwindcss').Config} */
|
||||||
export default {
|
export default {
|
||||||
|
purge: [
|
||||||
|
'./index.html',
|
||||||
|
'./src/**/*.{vue,js,ts,jsx,tsx}'
|
||||||
|
],
|
||||||
content: [
|
content: [
|
||||||
"./index.html",
|
"./index.html",
|
||||||
"./src/**/*.{js,ts,jsx,tsx,vue}",
|
"./src/**/*.{js,ts,jsx,tsx,vue}",
|
||||||
],
|
],
|
||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
|
colors: {
|
||||||
|
'ancient': '#d3d0c9',
|
||||||
|
'ancient_highlight': '#fcf8f5',
|
||||||
|
'ancient_shadow': '#bababa',
|
||||||
|
},
|
||||||
padding: {
|
padding: {
|
||||||
'small': '0.075rem',
|
'small': '0.075rem',
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user