From cb518b00efc8fe29df713e652450e90448340c29 Mon Sep 17 00:00:00 2001 From: Mitya Selivanov Date: Thu, 3 Oct 2024 08:32:25 +0200 Subject: Refactor --- rf64.c | 252 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 252 insertions(+) create mode 100755 rf64.c (limited to 'rf64.c') diff --git a/rf64.c b/rf64.c new file mode 100755 index 0000000..aeba85a --- /dev/null +++ b/rf64.c @@ -0,0 +1,252 @@ +#if 0 /* +#/ ================================================================ +#/ +#/ rf64.c +#/ +#/ Probabalistic floating-point numbers +#/ +#/ ---------------------------------------------------------------- +#/ +#/ (C) 2024 Mitya Selivanov , 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 +#include + +#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 +#include + +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 -- cgit v1.2.3