summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.clangd3
-rw-r--r--include/osm/types.h6
-rw-r--r--src/types.c148
3 files changed, 152 insertions, 5 deletions
diff --git a/.clangd b/.clangd
new file mode 100644
index 0000000..10b59db
--- /dev/null
+++ b/.clangd
@@ -0,0 +1,3 @@
+CompileFlags:
+ Add:
+ - -I../include
diff --git a/include/osm/types.h b/include/osm/types.h
index 5120098..08a0d03 100644
--- a/include/osm/types.h
+++ b/include/osm/types.h
@@ -57,7 +57,7 @@ bool osm_is_nan(OSMFloat f);
/// if positive infinity, returns 1
/// if negative infinity, returns -1
/// otherwise returns 0
-uint8_t osm_is_infinity(OSMFloat f);
+int8_t osm_is_infinity(OSMFloat f);
@@ -88,10 +88,10 @@ OSMColor osm_rgb_to_color(uint8_t r, uint8_t g, uint8_t b);
OSMColor osm_int_to_color(uint32_t c);
/// Deep copy a color struct
-OSMColor osm_color_copy(OSMColor color);
+OSMColor osm_color_copy(const OSMColor *color);
/// Free a color struct
-void osm_color_free(OSMColor color);
+void osm_color_free(OSMColor *color);
diff --git a/src/types.c b/src/types.c
index c9482c1..ff0459e 100644
--- a/src/types.c
+++ b/src/types.c
@@ -1,7 +1,17 @@
#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
#include "osm/types.h"
+/**
+ * WARNING: This file makes the *BOLD* assumption that
+ * your platform is using standard IEEE 754 floating
+ * point values by default for fp types.
+ */
+
OSMFloatBreakdown osm_float_to_break(OSMFloat f)
{
OSMFloatBreakdown out;
@@ -13,6 +23,51 @@ OSMFloatBreakdown osm_float_to_break(OSMFloat f)
return out;
}
+/// Function only to be used with number formats who's mantissa
+/// and fraction length are both smaller or equal to double
+/// precision IEEE 754 numbers
+OSMFloatBreakdown _osm_ieee754_enlarge(uint64_t d, uint16_t m_len, uint16_t f_len)
+{
+ OSMFloatBreakdown out = {0};
+
+ out.sign = (d >> (m_len + f_len)) & 1;
+
+ uint64_t mask = (1 << (m_len)) - 1; // Mantissa mask
+ out.mantissa = (d >> f_len) & mask; // Mantissa biased by the other type's bias
+ uint16_t bias = mask >> 1; // The other type's bias
+
+ mask = (1 << f_len) - 1;
+ out.fraction = d & mask;
+
+ if (out.mantissa >= bias)
+ {
+ // non-negative exponent
+ out.mantissa -= bias;
+ out.mantissa += 0x3ff;
+ }
+ else if (out.mantissa < bias && out.mantissa > 0)
+ {
+ out.mantissa = bias - out.mantissa; // true exponent (abs value)
+ out.mantissa = 0x3ff - out.mantissa; // corrected for double precision numbers (won't overflow since we use this function with smaller mantissa)
+ out.fraction = out.fraction << (52 - f_len); // corrected fraction based on difference in bit lengths
+ }
+
+ if (out.mantissa == 0)
+ {
+ if (out.fraction == 0)
+ return out;
+
+ // Denormal numbers (TODO)
+ out.mantissa = 0x3ff - bias; // corrected mantissa
+ out.fraction = out.fraction << (52 - f_len); // corrected fraction based on difference in bit lengths
+ bias = (uint16_t) ceil(log2(out.fraction));
+
+ }
+
+
+ return out;
+}
+
/*
* WARNING: This code assumes that the compiler
* supports IEEE 754 floating point numbers.
@@ -30,12 +85,12 @@ OSMFloatBreakdown osm_native_float_to_break(double d)
{
case 2: {
uint16_t bits = *(uint16_t *) &d;
- out.sign = bits >> 15;
+ out = _osm_ieee754_enlarge(bits, 5, 10);
} break;
case 4: {
uint32_t bits = * (uint32_t *) &d;
- out.sign = bits >> 31;
+ out = _osm_ieee754_enlarge(bits, 8, 23);
} break;
case 8: {
@@ -44,6 +99,7 @@ OSMFloatBreakdown osm_native_float_to_break(double d)
} break;
default:
+ fprintf(stderr, "\nERROR libopensmarts: unable to convert float from double to OSMFloat.\n");
break;
}
@@ -65,10 +121,23 @@ OSMFloat osm_break_to_float(OSMFloatBreakdown b)
return out;
}
+double _osm_ieee754_assemble(OSMFloatBreakdown b, uint16_t m_len, uint16_t f_len)
+{
+ double out = 0;
+ // Check
+ return out;
+}
+
/*
* WARNING: This code assumes that the compiler
* supports IEEE 754 floating point numbers.
*
+ * WARNING: This code flushes denormal values to zero
+ *
+ * WARNING: This code flushes out of bounds values to infinity
+ *
+ * INFO: This code keeps NaN values
+ *
* Should probably be updated with more formats if I was
* feeling frisky.
*/
@@ -90,6 +159,7 @@ double osm_break_to_native_float(OSMFloatBreakdown b)
} break;
default:
+ fprintf(stderr, "\nERROR libopensmarts: unable to convert float from OSMFloat to double.\n");
break;
}
@@ -114,3 +184,77 @@ OSMFloat osm_native_to_float(double d)
osm_native_float_to_break(d)
);
}
+
+bool osm_is_nan(OSMFloat f)
+{
+ OSMFloatBreakdown b = osm_float_to_break(f);
+ return b.mantissa == 0x3ff && b.fraction != 0;
+}
+
+int8_t osm_is_infinity(OSMFloat f)
+{
+ OSMFloatBreakdown b = osm_float_to_break(f);
+ if (b.mantissa == 0x3ff && b.fraction == 0)
+ {
+ if (b.sign)
+ return -1;
+ return 1;
+ }
+ return 0;
+}
+
+OSMColor osm_rgb_to_color(uint8_t r, uint8_t g, uint8_t b)
+{
+ OSMColor out = {
+ .r = r,
+ .g = g,
+ .b = b,
+ .extra = 0,
+ .ex = NULL,
+ .ex_names = NULL
+ };
+ return out;
+}
+
+OSMColor osm_color_copy(const OSMColor *color)
+{
+
+ OSMColor out = {
+ .r = color->r,
+ .g = color->g,
+ .b = color->b,
+ .extra = color->extra,
+ .ex = malloc(color->extra),
+ .ex_names = malloc(color->extra * sizeof(uint8_t *))
+ };
+
+ for (uint8_t i = 0; i < color->extra; i++)
+ {
+ // char should be just one byte long anyways
+ size_t len = strlen((char *)color->ex_names[i]) + 1;
+ uint8_t *buf = malloc(strlen((char *)color->ex_names[i]) + 1);
+ memcpy(buf, color->ex_names[i], len);
+ }
+
+ return out;
+}
+
+void osm_color_free(OSMColor *color)
+{
+ color->r = 0;
+ color->g = 0;
+ color->b = 0;
+
+ for (uint8_t i = 0; i < color->extra; i++)
+ {
+ free(color->ex_names[i]);
+ }
+
+ free(color->ex_names);
+ free(color->ex);
+
+ color->ex_names = NULL;
+ color->ex = NULL;
+
+ color->extra = 0;
+}