summaryrefslogtreecommitdiff
path: root/examples/rf64.c
diff options
context:
space:
mode:
Diffstat (limited to 'examples/rf64.c')
-rwxr-xr-xexamples/rf64.c252
1 files changed, 252 insertions, 0 deletions
diff --git a/examples/rf64.c b/examples/rf64.c
new file mode 100755
index 0000000..aeba85a
--- /dev/null
+++ b/examples/rf64.c
@@ -0,0 +1,252 @@
+#if 0 /*
+#/ ================================================================
+#/
+#/ rf64.c
+#/
+#/ Probabalistic floating-point numbers
+#/
+#/ ----------------------------------------------------------------
+#/
+#/ (C) 2024 Mitya Selivanov <guattari.tech>, MIT License
+#/
+#/ ================================================================
+#/
+#/ Self-compilation shell script
+#/
+SRC=${0##*./}
+BIN=${SRC%.*}
+gcc \
+ -Wall -Wextra -Werror -pedantic \
+ -Wno-old-style-declaration \
+ -Wno-missing-braces \
+ -Wno-unused-variable \
+ -Wno-unused-but-set-variable \
+ -Wno-unused-parameter \
+ -Wno-overlength-strings \
+ -O3 \
+ -fsanitize=undefined,address,leak -mshstk \
+ -D RF64_TESTS \
+ -o $BIN $SRC && \
+ ./$BIN $@ && rm $BIN
+exit $? # */
+#endif
+
+// ================================================================
+
+#ifndef TYPES_HEADER_GUARD_
+#define TYPES_HEADER_GUARD_
+
+typedef signed char i8;
+typedef signed short i16;
+typedef signed i32;
+typedef signed long long i64;
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned u32;
+typedef unsigned long long u64;
+typedef char c8;
+typedef int c32;
+typedef signed char b8;
+typedef float f32;
+typedef double f64;
+
+#endif // TYPES_HEADER_GUARD_
+
+// ================================================================
+
+#ifndef RF64_HEADER_GUARD_
+#define RF64_HEADER_GUARD_
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+
+#ifndef RF64_RAND
+static i32 rf64_rand(i32 min, i32 max) {
+ if (max <= min)
+ return min;
+ return min + (rand() % (max - min + 1));
+}
+
+#define RF64_RAND(min, max) rf64_rand((min), (max))
+#endif
+
+#define RF64_EXPONENT_NUM_BITS 30
+#define RF64_MANTISSA_NUM_BITS 32
+#define RF64_EXPONENT_ZERO (1 << (RF64_EXPONENT_NUM_BITS / 2))
+#define RF64_EXPONENT_MAX ((1 << RF64_EXPONENT_NUM_BITS) - 1)
+#define RF64_MANTISSA_MAX 0xffffffffu
+
+typedef struct {
+ u32 infinity : 1;
+ u32 sign : 1;
+ i32 exponent : RF64_EXPONENT_NUM_BITS;
+ u32 mantissa;
+} rf64;
+
+rf64 rf64_from_i64(i64 x);
+i64 i64_from_rf64(rf64 x);
+void rf64_inc(rf64 *x);
+void rf64_dec(rf64 *x);
+void rf64_add(rf64 *x, rf64 y);
+void rf64_sub(rf64 *x, rf64 y);
+void rf64_mul(rf64 *x, rf64 y);
+void rf64_div(rf64 *x, rf64 y);
+
+#endif // RF64_HEADER_GUARD_
+
+#ifndef RF64_HEADER
+#ifndef RF64_IMPL_GUARD_
+#define RF64_IMPL_GUARD_
+
+rf64 rf64_from_i64(i64 x) {
+ rf64 z = {
+ .sign = x < 0,
+ .exponent = RF64_EXPONENT_ZERO,
+ };
+
+ u64 a = z.sign ? -x : x;
+
+ while (a > RF64_MANTISSA_MAX) {
+ u64 loss_comp = (a & 1) == 1 ? RF64_RAND(0, 1) : 0;
+
+ z.exponent += 1;
+
+ a /= 2;
+ a += loss_comp;
+ }
+
+ z.mantissa = (u32) a;
+
+ return z;
+}
+
+i64 i64_from_rf64(rf64 x) {
+ assert(0);
+}
+
+void rf64_inc(rf64 *x) {
+ assert(0);
+}
+
+void rf64_dec(rf64 *x) {
+ assert(x != NULL);
+ if (x == NULL) return;
+
+ assert(0);
+}
+
+void rf64_add(rf64 *x, rf64 y) {
+ assert(x != NULL);
+ if (x == NULL) return;
+
+ assert(0);
+}
+
+void rf64_sub(rf64 *x, rf64 y) {
+ assert(x != NULL);
+ if (x == NULL) return;
+
+ assert(0);
+}
+
+void rf64_mul(rf64 *x, rf64 y) {
+ assert(x != NULL);
+ if (x == NULL) return;
+
+ assert(0);
+}
+
+void rf64_div(rf64 *x, rf64 y) {
+ assert(x != NULL);
+ if (x == NULL) return;
+
+ assert(0);
+}
+
+#ifdef RF64_TESTS
+
+#include <stdio.h>
+#include <string.h>
+
+void report_test(c8 *name, b8 success) {
+ i32 l = 20 - (i32) strlen(name);
+
+ printf("%s %.*s %s\n",
+ name,
+ l < 1 ? 1 : l,
+ "....................",
+ success ? "OK" : "FAIL"
+ );
+}
+
+#define TEST_(x) report_test(#x, test_##x())
+
+b8 test_from_i64() {
+ return 1
+ && rf64_from_i64( 0 ).infinity == 0
+ && rf64_from_i64( 0 ).sign == 0
+ && rf64_from_i64( 0 ).exponent == RF64_EXPONENT_ZERO
+ && rf64_from_i64( 0 ).mantissa == 0
+ && rf64_from_i64( 42 ).infinity == 0
+ && rf64_from_i64( 42 ).sign == 0
+ && rf64_from_i64( 42 ).exponent == RF64_EXPONENT_ZERO
+ && rf64_from_i64( 42 ).mantissa == 42
+ && rf64_from_i64(-42 ).infinity == 0
+ && rf64_from_i64(-42 ).sign == 1
+ && rf64_from_i64(-42 ).exponent == RF64_EXPONENT_ZERO
+ && rf64_from_i64(-42 ).mantissa == 42
+ && rf64_from_i64( 0xffffffff ).infinity == 0
+ && rf64_from_i64( 0xffffffff ).sign == 0
+ && rf64_from_i64( 0xffffffff ).exponent == RF64_EXPONENT_ZERO
+ && rf64_from_i64( 0xffffffff ).mantissa == 0xffffffff
+ && rf64_from_i64(-0xffffffffll ).infinity == 0
+ && rf64_from_i64(-0xffffffffll ).sign == 1
+ && rf64_from_i64(-0xffffffffll ).exponent == RF64_EXPONENT_ZERO
+ && rf64_from_i64(-0xffffffffll ).mantissa == 0xffffffff
+ && rf64_from_i64( 0x100000000ll).infinity == 0
+ && rf64_from_i64( 0x100000000ll).sign == 0
+ && rf64_from_i64( 0x100000000ll).exponent == RF64_EXPONENT_ZERO + 1
+ && rf64_from_i64( 0x100000000ll).mantissa == 0x80000000u
+ && rf64_from_i64(-0x100000000ll).infinity == 0
+ && rf64_from_i64(-0x100000000ll).sign == 1
+ && rf64_from_i64(-0x100000000ll).exponent == RF64_EXPONENT_ZERO + 1
+ && rf64_from_i64(-0x100000000ll).mantissa == 0x80000000u
+ && 1;
+}
+
+b8 test_to_i64() {
+ return 1
+ && i64_from_rf64(rf64_from_i64( 0 )) == 0
+ && i64_from_rf64(rf64_from_i64( 1 )) == 1
+ && i64_from_rf64(rf64_from_i64(-1 )) == -1
+ && i64_from_rf64(rf64_from_i64( 42 )) == 42
+ && i64_from_rf64(rf64_from_i64(-42 )) == -42
+ && i64_from_rf64(rf64_from_i64( 0xffffffff )) == 0xffffffff
+ && i64_from_rf64(rf64_from_i64(-0xffffffff )) == -0xffffffff
+ && i64_from_rf64(rf64_from_i64( 0x100000000ll )) == 0x100000000ll
+ && i64_from_rf64(rf64_from_i64(-0x100000000ll )) == -0x100000000ll
+ && i64_from_rf64(rf64_from_i64( 0x42000000000ll)) == 0x42000000000ll
+ && i64_from_rf64(rf64_from_i64(-0x42000000000ll)) == -0x42000000000ll
+ && 1;
+}
+
+i32 main(i32 argc, c8 **argv) {
+ (void) argc;
+ (void) argv;
+
+ TEST_(from_i64);
+ TEST_(to_i64);
+
+ return 0;
+}
+
+#undef TEST_
+
+#endif // RF64_TESTS
+
+#endif // RF64_IMPL_GUARD_
+#endif // RF64_HEADER