diff options
author | Kyle Gunger <kgunger12@gmail.com> | 2024-05-04 02:39:07 -0400 |
---|---|---|
committer | Kyle Gunger <kgunger12@gmail.com> | 2024-05-04 02:39:07 -0400 |
commit | a85727c41263b83f5363b43a15ba02317f3b5081 (patch) | |
tree | 34cf516611cff0756db12029ad3062e2d0c55375 | |
parent | 50871e715812060a8dfb515fe2b432b1778583d6 (diff) |
Color copy and free
-rw-r--r-- | .clangd | 3 | ||||
-rw-r--r-- | include/osm/types.h | 6 | ||||
-rw-r--r-- | src/types.c | 148 |
3 files changed, 152 insertions, 5 deletions
@@ -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; +} |