From 1fe38f90bbfafae7f4d8ab4cc9a351f068d6ac00 Mon Sep 17 00:00:00 2001
From: Peter Gerwinski <peter.gerwinski@hs-bochum.de>
Date: Mon, 17 Apr 2023 18:59:09 +0200
Subject: [PATCH] Weitere Beispiele 17.4.2023: Gleitkommazahlen

---
 20230417/bs-20230417.txt   |  43 +++++++++
 20230417/chardev-2.c       | 185 +++++++++++++++++++++++++++++++++++++
 20230417/decode-float-01.c |  18 ++++
 20230417/decode-float-02.c |  20 ++++
 20230417/deriv-01.c        |  25 +++++
 20230417/deriv-01.gp       |   4 +
 20230417/deriv-02.c        |  25 +++++
 20230417/deriv-02.gp       |   4 +
 20230417/deriv-03.c        |  25 +++++
 20230417/deriv-03.gp       |   4 +
 20230417/deriv-04.c        |  26 ++++++
 20230417/deriv-04.gp       |   4 +
 20230417/deriv-05.c        |  26 ++++++
 20230417/deriv-05.gp       |   4 +
 20230417/dgl-01.c          |  14 +++
 20230417/dgl-01.gp         |   3 +
 20230417/sum-10.c          |  38 ++++++++
 20230417/sum-11.c          |  38 ++++++++
 20230417/sum-12.c          |  36 ++++++++
 20230417/sum-13.c          |  36 ++++++++
 20 files changed, 578 insertions(+)
 create mode 100644 20230417/bs-20230417.txt
 create mode 100644 20230417/chardev-2.c
 create mode 100644 20230417/decode-float-01.c
 create mode 100644 20230417/decode-float-02.c
 create mode 100644 20230417/deriv-01.c
 create mode 100644 20230417/deriv-01.gp
 create mode 100644 20230417/deriv-02.c
 create mode 100644 20230417/deriv-02.gp
 create mode 100644 20230417/deriv-03.c
 create mode 100644 20230417/deriv-03.gp
 create mode 100644 20230417/deriv-04.c
 create mode 100644 20230417/deriv-04.gp
 create mode 100644 20230417/deriv-05.c
 create mode 100644 20230417/deriv-05.gp
 create mode 100644 20230417/dgl-01.c
 create mode 100644 20230417/dgl-01.gp
 create mode 100644 20230417/sum-10.c
 create mode 100644 20230417/sum-11.c
 create mode 100644 20230417/sum-12.c
 create mode 100644 20230417/sum-13.c

diff --git a/20230417/bs-20230417.txt b/20230417/bs-20230417.txt
new file mode 100644
index 0000000..8e679b1
--- /dev/null
+++ b/20230417/bs-20230417.txt
@@ -0,0 +1,43 @@
+Gleitkommazahlen, 17.04.2023, 18:12:52
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+https://de.wikipedia.org/wiki/IEEE_754-2008
+
+Die Zahl        2.351 · 10^5
+kann man auch 0.2351 · 10^6
+oder         0.02351 · 10^7
+schreiben.
+
+Welche dieser Varianten ist hinsichtlich Speicherplatz am ineffizientesten?
+0.02351 · 10^7 --> benötigt 7 Zeichen für die Mantisse
+
+Welche dieser Varianten ist hinsichtlich Speicherplatz am effizientesten?
+Beide:
+2.351 · 10^5   4 Ziffern für die Mantisse (Konvention: immer 1 Ziffer vor dem Komma)
+0.2351 · 10^6  4 Ziffern für die Mantisse (Konvention: immer eine 0 vor dem Komma)
+
+Bei Binärzahlen:
+
+  1.11011 · 2^101   (Konvention: immer eine 1 vor dem Komma)  "normalisierte Zahl"
+ 0.111011 · 2^110   (Konvention: immer eine 0 vor dem Komma)
+
+--> Man braucht die Ziffer vor dem Komma nicht mit zu speichern (wegen Konvention).
+    Wenn vor dem Komma eine 0 steht, muß dahinter eine 1 stehen (wegen Konvention).
+--> Wieder beide gleich. (In beiden Fällen brauchen wir nur 5 Binärziffern zu speichern.)
+
+Standard: IEEE 754 (2008)
+Gleitkommazahlen immer normalisiert speichern, die führende 1 nicht mitspeichern.
+
+Beispiel: Kodierung einer 32-Bit-Gleitkommazahl:
+https://upload.wikimedia.org/wikipedia/commons/5/56/IEEE-754-single.svg
+
+V EEEEEEEE MMMMMMMMMMMMMMMMMMMMMMM
+
+V = Vorzeichen-Bit
+E = "Charakteristik"    Siehe: https://de.wikipedia.org/wiki/IEEE_754
+M = Mantisse
+
+Aufgabe: Schreibe ein Progrämmchen, das eine float-Variable lesbar ausgibt,
+         ohne printf() mit "%f" zu verwenden, also durch Analysieren der Bits.
+Die Aufgabe ist erfüllt, wenn wir die Mantisse (mit Vorzeichen) und den (binären)
+Exponenten kennen. Um danach die Dezimalzahl korrekt auszugeben, ist auch
+Gleitkommaarithmetik sowie printf() mit "%f" (oder besser: "%e") erlaubt.
diff --git a/20230417/chardev-2.c b/20230417/chardev-2.c
new file mode 100644
index 0000000..c7d58f1
--- /dev/null
+++ b/20230417/chardev-2.c
@@ -0,0 +1,185 @@
+/*
+ *  chardev.c: Creates a read-only char device that says how many times
+ *  you've read from the dev file
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <asm/uaccess.h>	/* for put_user */
+
+MODULE_LICENSE("GPL");
+
+/*  
+ *  Prototypes - this would normally go in a .h file
+ */
+int init_module(void);
+void cleanup_module(void);
+static int device_open(struct inode *, struct file *);
+static int device_release(struct inode *, struct file *);
+static ssize_t device_read(struct file *, char *, size_t, loff_t *);
+static ssize_t device_write(struct file *, const char *, size_t, loff_t *);
+
+struct class *dev_Class;
+struct device *chr_dev;
+
+#define SUCCESS 0
+#define DEVICE_NAME "chardev"	/* Dev name as it appears in /proc/devices   */
+#define BUF_LEN 80		/* Max length of the message from the device */
+
+/* 
+ * Global variables are declared as static, so are global within the file. 
+ */
+
+static int Major;		/* Major number assigned to our device driver */
+static int Device_Open = 0;	/* Is device open?  
+				 * Used to prevent multiple access to device */
+static char msg[BUF_LEN];	/* The msg the device will give when asked */
+static char *msg_Ptr;
+
+static struct file_operations fops = {
+	.read = device_read,
+	.write = device_write,
+	.open = device_open,
+	.release = device_release
+};
+
+/*
+ * This function is called when the module is loaded
+ */
+int init_module(void)
+{
+        Major = register_chrdev(0, DEVICE_NAME, &fops);
+
+	if (Major < 0) {
+	  printk(KERN_ALERT "Registering char device failed with %d\n", Major);
+	  return Major;
+	}
+
+        // Create module class
+        printk(KERN_INFO "Creating device class ...\n");
+        dev_Class = class_create(THIS_MODULE,DEVICE_NAME);
+        if( dev_Class == NULL)
+        {
+            printk( KERN_ALERT "Error! Class couldn't be created!\n" );
+            return 1 ;
+        }
+        printk( KERN_INFO "Class created!\n" );
+        // Create device in /dev/...
+        printk(KERN_INFO "Creating device\n");
+        chr_dev = device_create(dev_Class, NULL, MKDEV(Major,0), NULL, DEVICE_NAME);
+
+	printk(KERN_INFO "I was assigned major number %d. To talk to\n", Major);
+	printk(KERN_INFO "the driver, create a dev file with\n");
+	printk(KERN_INFO "'mknod /dev/%s c %d 0'.\n", DEVICE_NAME, Major);
+	printk(KERN_INFO "Try various minor numbers. Try to cat and echo to\n");
+	printk(KERN_INFO "the device file.\n");
+	printk(KERN_INFO "Remove the device file and module when done.\n");
+
+	return SUCCESS;
+}
+
+/*
+ * This function is called when the module is unloaded
+ */
+void cleanup_module(void)
+{
+	/* 
+	 * Unregister the device 
+	 */
+	unregister_chrdev(Major, DEVICE_NAME);
+}
+
+/*
+ * Methods
+ */
+
+/* 
+ * Called when a process tries to open the device file, like
+ * "cat /dev/mycharfile"
+ */
+static int device_open(struct inode *inode, struct file *file)
+{
+	static int counter = 0;
+
+	if (Device_Open)
+		return -EBUSY;
+
+	Device_Open++;
+	sprintf(msg, "I already told you %d times Hello world!\n", counter++);
+	msg_Ptr = msg;
+	try_module_get(THIS_MODULE);
+
+	return SUCCESS;
+}
+
+/* 
+ * Called when a process closes the device file.
+ */
+static int device_release(struct inode *inode, struct file *file)
+{
+	Device_Open--;		/* We're now ready for our next caller */
+
+	/* 
+	 * Decrement the usage count, or else once you opened the file, you'll
+	 * never get get rid of the module. 
+	 */
+	module_put(THIS_MODULE);
+
+	return 0;
+}
+
+/* 
+ * Called when a process, which already opened the dev file, attempts to
+ * read from it.
+ */
+static ssize_t device_read(struct file *filp,	/* see include/linux/fs.h   */
+			   char *buffer,	/* buffer to fill with data */
+			   size_t length,	/* length of the buffer     */
+			   loff_t * offset)
+{
+	/*
+	 * Number of bytes actually written to the buffer 
+	 */
+	int bytes_read = 0;
+
+	/*
+	 * If we're at the end of the message, 
+	 * return 0 signifying end of file 
+	 */
+	if (*msg_Ptr == 0)
+		return 0;
+
+	/* 
+	 * Actually put the data into the buffer 
+	 */
+	while (length && *msg_Ptr) {
+
+		/* 
+		 * The buffer is in the user data segment, not the kernel 
+		 * segment so "*" assignment won't work.  We have to use 
+		 * put_user which copies data from the kernel data segment to
+		 * the user data segment. 
+		 */
+		put_user(*(msg_Ptr++), buffer++);
+
+		length--;
+		bytes_read++;
+	}
+
+	/* 
+	 * Most read functions return the number of bytes put into the buffer
+	 */
+	return bytes_read;
+}
+
+/*  
+ * Called when a process writes to dev file: echo "hi" > /dev/hello 
+ */
+static ssize_t
+device_write(struct file *filp, const char *buff, size_t len, loff_t * off)
+{
+	printk(KERN_ALERT "Sorry, this operation isn't supported.\n");
+	return -EINVAL;
+}
diff --git a/20230417/decode-float-01.c b/20230417/decode-float-01.c
new file mode 100644
index 0000000..9eaf2c8
--- /dev/null
+++ b/20230417/decode-float-01.c
@@ -0,0 +1,18 @@
+#include <stdio.h>
+#include <stdint.h>
+
+#define B 127
+
+int main (void)
+{
+  float G = 6.6743e-11;
+  uint32_t *g = (uint32_t *) &G;
+  int8_t sign = !!(*g & (1 << 31));
+  uint8_t ch = (*g >> 23);
+  int ex = ch - B;
+  int32_t mant = (*g & 0x7fffff) | 0x800000;
+  if (sign)
+    mant *= -1;
+  printf ("%d·2^%d\n", mant, ex);
+  return 0;
+}
diff --git a/20230417/decode-float-02.c b/20230417/decode-float-02.c
new file mode 100644
index 0000000..ca22690
--- /dev/null
+++ b/20230417/decode-float-02.c
@@ -0,0 +1,20 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <math.h>
+
+#define B 127
+
+int main (void)
+{
+  float G = 6.6743e-11;
+  uint32_t *g = (uint32_t *) &G;
+  int8_t sign = !!(*g & (1 << 31));
+  uint8_t ch = (*g >> 23);
+  int ex = ch - B - 23;
+  int32_t mant = (*g & 0x7fffff) | 0x800000;
+  if (sign)
+    mant *= -1;
+  printf ("%d·2^%d\n", mant, ex);
+  printf ("= %e\n", mant * pow (2.0, ex));
+  return 0;
+}
diff --git a/20230417/deriv-01.c b/20230417/deriv-01.c
new file mode 100644
index 0000000..610980c
--- /dev/null
+++ b/20230417/deriv-01.c
@@ -0,0 +1,25 @@
+#include <stdio.h>
+
+float f (float x)
+{
+  return x * x;
+}
+
+float df_a (float x)
+{
+  return 2.0 * x;
+}
+
+float df_n (float x)
+{
+  float dx = 0.0000001;
+  float df = f (x + 0.5 * dx) - f (x - 0.5 * dx);
+  return df / dx;
+}
+
+int main (void)
+{
+  for (float x = -3.0; x <= 3.0; x += 0.1)
+    printf ("%10f%10f%10f%10f\n", x, f (x), df_a (x), df_n (x));
+  return 0;
+}
diff --git a/20230417/deriv-01.gp b/20230417/deriv-01.gp
new file mode 100644
index 0000000..109ff33
--- /dev/null
+++ b/20230417/deriv-01.gp
@@ -0,0 +1,4 @@
+plot "deriv-01.dat" using 1:2 with lines title "f(x)", \
+     "deriv-01.dat" using 1:3 with lines title "df_a(x)", \
+     "deriv-01.dat" using 1:4 with lines lc "red" dashtype "-" title "df_n(x)"
+pause -1
diff --git a/20230417/deriv-02.c b/20230417/deriv-02.c
new file mode 100644
index 0000000..14235c9
--- /dev/null
+++ b/20230417/deriv-02.c
@@ -0,0 +1,25 @@
+#include <stdio.h>
+
+float f (float x)
+{
+  return x * x * x;
+}
+
+float df_a (float x)
+{
+  return 3.0 * x * x;
+}
+
+float df_n (float x)
+{
+  float dx = 0.1;
+  float df = f (x + 0.5 * dx) - f (x - 0.5 * dx);
+  return df / dx;
+}
+
+int main (void)
+{
+  for (float x = -3.0; x <= 3.0; x += 0.1)
+    printf ("%11f %11f %11f %11f\n", x, f (x), df_a (x), df_n (x));
+  return 0;
+}
diff --git a/20230417/deriv-02.gp b/20230417/deriv-02.gp
new file mode 100644
index 0000000..a0a097a
--- /dev/null
+++ b/20230417/deriv-02.gp
@@ -0,0 +1,4 @@
+plot "deriv-02.dat" using 1:2 with lines title "f(x)", \
+     "deriv-02.dat" using 1:3 with lines title "df_a(x)", \
+     "deriv-02.dat" using 1:4 with lines lc "red" dashtype "-" title "df_n(x)"
+pause -1
diff --git a/20230417/deriv-03.c b/20230417/deriv-03.c
new file mode 100644
index 0000000..79665ff
--- /dev/null
+++ b/20230417/deriv-03.c
@@ -0,0 +1,25 @@
+#include <stdio.h>
+
+float f (float x)
+{
+  return x * x * x;
+}
+
+float df_a (float x)
+{
+  return 3.0 * x * x;
+}
+
+float df_n (float x)
+{
+  float dx = 0.0000001;
+  float df = f (x + dx) - f (x);
+  return df / dx;
+}
+
+int main (void)
+{
+  for (float x = -3.0; x <= 3.0; x += 0.1)
+    printf ("%11f %11f %11f %11f\n", x, f (x), df_a (x), df_n (x));
+  return 0;
+}
diff --git a/20230417/deriv-03.gp b/20230417/deriv-03.gp
new file mode 100644
index 0000000..34059e0
--- /dev/null
+++ b/20230417/deriv-03.gp
@@ -0,0 +1,4 @@
+plot "deriv-03.dat" using 1:2 with lines title "f(x)", \
+     "deriv-03.dat" using 1:3 with lines title "df_a(x)", \
+     "deriv-03.dat" using 1:4 with lines lc "red" dashtype "-" title "df_n(x)"
+pause -1
diff --git a/20230417/deriv-04.c b/20230417/deriv-04.c
new file mode 100644
index 0000000..7534ea5
--- /dev/null
+++ b/20230417/deriv-04.c
@@ -0,0 +1,26 @@
+#include <stdio.h>
+#include <math.h>
+
+float f (float x)
+{
+  return pow (3, x);  /* = exp (x * log (3)) */
+}
+
+float df_a (float x)
+{
+  return log (3) * pow (3, x);
+}
+
+float df_n (float x)
+{
+  float dx = 0.0000001;
+  float df = f (x + dx) - f (x);
+  return df / dx;
+}
+
+int main (void)
+{
+  for (float x = -3.0; x <= 3.0; x += 0.1)
+    printf ("%11f %11f %11f %11f\n", x, f (x), df_a (x), df_n (x));
+  return 0;
+}
diff --git a/20230417/deriv-04.gp b/20230417/deriv-04.gp
new file mode 100644
index 0000000..18e76f1
--- /dev/null
+++ b/20230417/deriv-04.gp
@@ -0,0 +1,4 @@
+plot "deriv-04.dat" using 1:2 with lines title "f(x)", \
+     "deriv-04.dat" using 1:3 with lines title "df_a(x)", \
+     "deriv-04.dat" using 1:4 with lines lc "red" dashtype "-" title "df_n(x)"
+pause -1
diff --git a/20230417/deriv-05.c b/20230417/deriv-05.c
new file mode 100644
index 0000000..9569a4a
--- /dev/null
+++ b/20230417/deriv-05.c
@@ -0,0 +1,26 @@
+#include <stdio.h>
+#include <math.h>
+
+float f (float x)
+{
+  return sin (1.0 / x);
+}
+
+float df_a (float x)
+{
+  return -cos (1.0 / x) / (x * x);  /* pow (x, 2) würde exp (x * log (2)) berechnen --> teuer */
+}
+
+float df_n (float x)
+{
+  float dx = 0.0000001;
+  float df = f (x + dx) - f (x);
+  return df / dx;
+}
+
+int main (void)
+{
+  for (float x = 0.3; x <= 3.0; x += 0.1)
+    printf ("%11f %11f %11f %11f\n", x, f (x), df_a (x), df_n (x));
+  return 0;
+}
diff --git a/20230417/deriv-05.gp b/20230417/deriv-05.gp
new file mode 100644
index 0000000..122896c
--- /dev/null
+++ b/20230417/deriv-05.gp
@@ -0,0 +1,4 @@
+plot "deriv-05.dat" using 1:2 with lines title "f(x)", \
+     "deriv-05.dat" using 1:3 with lines title "df_a(x)", \
+     "deriv-05.dat" using 1:4 with lines lc "red" dashtype "-" title "df_n(x)"
+pause -1
diff --git a/20230417/dgl-01.c b/20230417/dgl-01.c
new file mode 100644
index 0000000..71b4e3f
--- /dev/null
+++ b/20230417/dgl-01.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <math.h>
+
+int main (void)
+{
+  float dx = 0.000001;
+  float y = 1.0;
+  for (float x = 0.0; x <= 4.0; x += dx)
+    {
+      printf ("%10f%10f%10f\n", x, exp (x), y);
+      y += y * dx;
+    }
+  return 0;
+}
diff --git a/20230417/dgl-01.gp b/20230417/dgl-01.gp
new file mode 100644
index 0000000..681b5db
--- /dev/null
+++ b/20230417/dgl-01.gp
@@ -0,0 +1,3 @@
+plot "dgl-01.dat" using 1:2 with lines title "exp(x)", \
+     "dgl-01.dat" using 1:3 with lines dashtype "-" title "y(x)"
+pause -1
diff --git a/20230417/sum-10.c b/20230417/sum-10.c
new file mode 100644
index 0000000..ebdaef4
--- /dev/null
+++ b/20230417/sum-10.c
@@ -0,0 +1,38 @@
+#include <stdio.h>
+#include <math.h>
+
+/* exp(x) = Summe aller x^n / n! für n = 0 bis Unendlich */
+/* n! = 1 · 2 · 3 · ... · n */
+
+int main (void)
+{
+  float x = 2.0;
+  printf ("%0.9f\n", exp (x));
+  float S = 0.0;
+  for (int i = 0; i <= 120; i++)
+    {
+      float P = 1.0;
+      float F = 1.0;
+      for (int j = 1; j <= i; j++)
+        {
+          P *= x;
+          F *= j;
+        }
+      S += P / F;
+    }
+  printf ("%0.9f\n", S);
+  S = 0.0;
+  for (int i = 120; i >= 0; i--)
+    {
+      float P = 1.0;
+      float F = 1.0;
+      for (int j = 1; j <= i; j++)
+        {
+          P *= x;
+          F *= j;
+        }
+      S += P / F;
+    }
+  printf ("%0.9f\n", S);
+  return 0;
+}
diff --git a/20230417/sum-11.c b/20230417/sum-11.c
new file mode 100644
index 0000000..3925247
--- /dev/null
+++ b/20230417/sum-11.c
@@ -0,0 +1,38 @@
+#include <stdio.h>
+#include <math.h>
+
+/* exp(x) = Summe aller x^n / n! für n = 0 bis Unendlich */
+/* n! = 1 · 2 · 3 · ... · n */
+
+int main (void)
+{
+  float x = 2.0;
+  printf ("%0.9f\n", exp (x));
+  float S = 0.0;
+  for (int i = 0; i <= 200; i++)
+    {
+      float P = 1.0;
+      float F = 1.0;
+      for (int j = 1; j <= i; j++)
+        {
+          P *= x;
+          F *= j;
+        }
+      S += P / F;
+    }
+  printf ("%0.9f\n", S);
+  S = 0.0;
+  for (int i = 200; i >= 0; i--)
+    {
+      float P = 1.0;
+      float F = 1.0;
+      for (int j = 1; j <= i; j++)
+        {
+          P *= x;
+          F *= j;
+        }
+      S += P / F;
+    }
+  printf ("%0.9f\n", S);
+  return 0;
+}
diff --git a/20230417/sum-12.c b/20230417/sum-12.c
new file mode 100644
index 0000000..4bd4842
--- /dev/null
+++ b/20230417/sum-12.c
@@ -0,0 +1,36 @@
+#include <stdio.h>
+#include <math.h>
+
+/* exp(x) = Summe aller x^n / n! für n = 0 bis Unendlich */
+/* n! = 1 · 2 · 3 · ... · n */
+
+int main (void)
+{
+  float x = 2.0;
+  printf ("%0.9f\n", exp (x));
+  float S = 0.0;
+  for (int i = 0; i <= 200; i++)
+    {
+      float acc = 1.0;
+      for (int j = 1; j <= i; j++)
+        {
+          acc *= x;
+          acc /= j;
+        }
+      S += acc;
+    }
+  printf ("%0.9f\n", S);
+  S = 0.0;
+  for (int i = 200; i >= 0; i--)
+    {
+      float acc = 1.0;
+      for (int j = 1; j <= i; j++)
+        {
+          acc *= x;
+          acc /= j;
+        }
+      S += acc;
+    }
+  printf ("%0.9f\n", S);
+  return 0;
+}
diff --git a/20230417/sum-13.c b/20230417/sum-13.c
new file mode 100644
index 0000000..dd3c5a5
--- /dev/null
+++ b/20230417/sum-13.c
@@ -0,0 +1,36 @@
+#include <stdio.h>
+#include <math.h>
+
+/* exp(x) = Summe aller x^n / n! für n = 0 bis Unendlich */
+/* n! = 1 · 2 · 3 · ... · n */
+
+int main (void)
+{
+  float x = 2.0;
+  printf ("%0.9f\n", exp (x));
+  float S = 0.0;
+  for (int i = 0; i <= 1000; i++)
+    {
+      float acc = 1.0;
+      for (int j = 1; j <= i; j++)
+        {
+          acc *= x;
+          acc /= j;
+        }
+      S += acc;
+    }
+  printf ("%0.9f\n", S);
+  S = 0.0;
+  for (int i = 1000; i >= 0; i--)
+    {
+      float acc = 1.0;
+      for (int j = 1; j <= i; j++)
+        {
+          acc *= x;
+          acc /= j;
+        }
+      S += acc;
+    }
+  printf ("%0.9f\n", S);
+  return 0;
+}
-- 
GitLab